~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Andrew Bennetts
  • Date: 2010-01-12 03:53:21 UTC
  • mfrom: (4948 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4964.
  • Revision ID: andrew.bennetts@canonical.com-20100112035321-hofpz5p10224ryj3
Merge lp:bzr, resolving conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Black-box tests for bzr handling non-ascii characters."""
18
18
 
 
19
import os
19
20
import sys
20
 
import os
21
 
 
22
 
from bzrlib import osutils, urlutils
23
 
from bzrlib.tests import TestCaseWithTransport, TestSkipped
24
 
from bzrlib.trace import mutter, note
25
 
 
26
 
 
27
 
class TestNonAscii(TestCaseWithTransport):
 
21
 
 
22
from bzrlib import (
 
23
    osutils,
 
24
    tests,
 
25
    urlutils,
 
26
    )
 
27
from bzrlib.tests import EncodingAdapter
 
28
 
 
29
 
 
30
def load_tests(standard_tests, module, loader):
 
31
    return tests.multiply_tests(standard_tests,
 
32
                                EncodingAdapter.encoding_scenarios,
 
33
                                loader.suiteClass())
 
34
 
 
35
 
 
36
class TestNonAscii(tests.TestCaseWithTransport):
28
37
    """Test that bzr handles files/committers/etc which are non-ascii."""
29
38
 
30
39
    def setUp(self):
31
40
        super(TestNonAscii, self).setUp()
32
 
        self._orig_email = os.environ.get('BZR_EMAIL', None)
33
 
        self._orig_encoding = osutils._cached_user_encoding
 
41
        self._check_can_encode_paths()
34
42
 
 
43
        self.addCleanup(setattr, osutils, "_cached_user_encoding",
 
44
            osutils._cached_user_encoding)
35
45
        osutils._cached_user_encoding = self.encoding
36
46
        email = self.info['committer'] + ' <joe@foo.com>'
37
47
        os.environ['BZR_EMAIL'] = email.encode(osutils.get_user_encoding())
38
48
        self.create_base()
39
49
 
40
 
    def tearDown(self):
41
 
        if self._orig_email is not None:
42
 
            os.environ['BZR_EMAIL'] = self._orig_email
43
 
        else:
44
 
            if os.environ.get('BZR_EMAIL', None) is not None:
45
 
                del os.environ['BZR_EMAIL']
46
 
        osutils._cached_user_encoding = self._orig_encoding
47
 
        super(TestNonAscii, self).tearDown()
48
 
 
49
50
    def run_bzr_decode(self, args, encoding=None, fail=False, retcode=None,
50
 
                        working_dir=None):
 
51
                       working_dir=None):
51
52
        """Run bzr and decode the output into a particular encoding.
52
53
 
53
54
        Returns a string containing the stdout output from bzr.
54
55
 
55
 
        :param fail: If true, the operation is expected to fail with 
 
56
        :param fail: If true, the operation is expected to fail with
56
57
            a UnicodeError.
57
58
        """
58
59
        if encoding is None:
59
60
            encoding = osutils.get_user_encoding()
60
61
        try:
61
 
            out = self.run_bzr(args, output_encoding=encoding, encoding=encoding,
62
 
                retcode=retcode, working_dir=working_dir)[0]
 
62
            out = self.run_bzr(args,
 
63
                               output_encoding=encoding, encoding=encoding,
 
64
                               retcode=retcode, working_dir=working_dir)[0]
63
65
            return out.decode(encoding)
64
66
        except UnicodeError, e:
65
67
            if not fail:
72
74
            if fail:
73
75
                self.fail("Expected UnicodeError not raised")
74
76
 
75
 
    def create_base(self):
76
 
        fs_enc = sys.getfilesystemencoding()
 
77
    def _check_OSX_can_roundtrip(self, path, fs_enc=None):
 
78
        """Stop the test if it's about to fail or errors out.
 
79
 
 
80
        Until we get proper support on OSX for accented paths (in fact, any
 
81
        path whose NFD decomposition is different than the NFC one), this is
 
82
        the best way to keep test active (as opposed to disabling them
 
83
        completely). This is a stop gap. The tests should at least be rewritten
 
84
        so that the failing ones are clearly separated from the passing ones.
 
85
        """
 
86
        if fs_enc is None:
 
87
            fs_enc = osutils._fs_enc
 
88
        if sys.platform == 'darwin':
 
89
            encoded = path.encode(fs_enc)
 
90
            import unicodedata
 
91
            normal_thing = unicodedata.normalize('NFD', path)
 
92
            mac_encoded = normal_thing.encode(fs_enc)
 
93
            if mac_encoded != encoded:
 
94
                raise tests.KnownFailure(
 
95
                    'Unable to roundtrip path %r on OSX filesystem'
 
96
                    ' using encoding "%s"'
 
97
                    % (path, fs_enc))
 
98
 
 
99
    def _check_can_encode_paths(self):
 
100
        fs_enc = osutils._fs_enc
77
101
        terminal_enc = osutils.get_terminal_encoding()
78
102
        fname = self.info['filename']
79
103
        dir_name = self.info['directory']
81
105
            try:
82
106
                thing.encode(fs_enc)
83
107
            except UnicodeEncodeError:
84
 
                raise TestSkipped(('Unable to represent path %r'
85
 
                                   ' in filesystem encoding "%s"')
86
 
                                    % (thing, fs_enc))
 
108
                raise tests.TestSkipped(
 
109
                    'Unable to represent path %r in filesystem encoding "%s"'
 
110
                    % (thing, fs_enc))
87
111
            try:
88
112
                thing.encode(terminal_enc)
89
113
            except UnicodeEncodeError:
90
 
                raise TestSkipped(('Unable to represent path %r'
91
 
                                   ' in terminal encoding "%s"'
92
 
                                   ' (even though it is valid in'
93
 
                                   ' filesystem encoding "%s")')
94
 
                                   % (thing, terminal_enc, fs_enc))
 
114
                raise tests.TestSkipped(
 
115
                    'Unable to represent path %r in terminal encoding "%s"'
 
116
                    ' (even though it is valid in filesystem encoding "%s")'
 
117
                    % (thing, terminal_enc, fs_enc))
95
118
 
 
119
    def create_base(self):
96
120
        wt = self.make_branch_and_tree('.')
97
121
        self.build_tree_contents([('a', 'foo\n')])
98
122
        wt.add('a')
103
127
        wt.add('b')
104
128
        wt.commit(self.info['message'])
105
129
 
 
130
        fname = self.info['filename']
106
131
        self.build_tree_contents([(fname, 'unicode filename\n')])
107
132
        wt.add(fname)
108
133
        wt.commit(u'And a unicode file\n')
109
134
        self.wt = wt
 
135
        # FIXME: We don't check that the add went well, in fact, it doesn't on
 
136
        # OSX (when LC_ALL is set correctly) because the added path doesn't
 
137
        # match the one used on OSX. But checking here will require more
 
138
        # invasive changes than adding the _check_OSX_can_roundtrip(), so I
 
139
        # punt for now -- vila 20090702
110
140
 
111
141
    def test_status(self):
112
142
        self.build_tree_contents(
113
143
            [(self.info['filename'], 'changed something\n')])
114
144
        txt = self.run_bzr_decode('status')
 
145
        self._check_OSX_can_roundtrip(self.info['filename'])
115
146
        self.assertEqual(u'modified:\n  %s\n' % (self.info['filename'],), txt)
116
147
 
117
148
        txt = self.run_bzr_decode('status', encoding='ascii')
125
156
        txt = self.run_bzr('cat b')[0]
126
157
        self.assertEqual('non-ascii \xFF\xFF\xFC\xFB\x00 in b\n', txt)
127
158
 
 
159
        self._check_OSX_can_roundtrip(self.info['filename'])
128
160
        txt = self.run_bzr(['cat', self.info['filename']])[0]
129
161
        self.assertEqual('unicode filename\n', txt)
130
162
 
158
190
 
159
191
    def test_inventory(self):
160
192
        txt = self.run_bzr_decode('inventory')
 
193
        self._check_OSX_can_roundtrip(self.info['filename'])
161
194
        self.assertEqual(['a', 'b', self.info['filename']],
162
195
                         txt.splitlines())
163
196
 
201
234
        os.mkdir(dirname)
202
235
        self.wt.add(dirname)
203
236
        txt = self.run_bzr_decode(['mv', fname1, fname2, dirname])
 
237
        self._check_OSX_can_roundtrip(self.info['filename'])
204
238
        self.assertEqual([u'%s => %s/%s' % (fname1, dirname, fname1),
205
239
                          u'%s => %s/%s' % (fname2, dirname, fname2)]
206
240
                         , txt.splitlines())
251
285
        # TODO: jam 20060427 For drastically improving performance, we probably
252
286
        #       could create a local repository, so it wouldn't have to copy
253
287
        #       the files around as much.
 
288
        # Note that the tests don't actually fail, but if we don't set this
 
289
        # flag, we end up getting "Lock was not Unlocked" warnings
254
290
 
255
291
        dirname = self.info['directory']
256
292
        self.run_bzr_decode(['push', dirname])
298
334
        fname = self.info['filename']
299
335
        txt = self.run_bzr_decode(['file-id', fname])
300
336
 
301
 
        # TODO: jam 20060106 We don't support non-ascii file ids yet, 
 
337
        # TODO: jam 20060106 We don't support non-ascii file ids yet,
302
338
        #       so there is nothing which would fail in ascii encoding
303
339
        #       This *should* be retcode=3
304
340
        txt = self.run_bzr_decode(['file-id', fname], encoding='ascii')
313
349
        self.wt.add('base')
314
350
        self.wt.add('base/'+dirname)
315
351
        path = osutils.pathjoin('base', dirname, fname)
 
352
        self._check_OSX_can_roundtrip(self.info['filename'])
316
353
        self.wt.rename_one(fname, path)
317
354
        self.wt.commit('moving things around')
318
355
 
319
356
        txt = self.run_bzr_decode(['file-path', path])
320
357
 
321
 
        # TODO: jam 20060106 We don't support non-ascii file ids yet, 
 
358
        # TODO: jam 20060106 We don't support non-ascii file ids yet,
322
359
        #       so there is nothing which would fail in ascii encoding
323
360
        #       This *should* be retcode=3
324
361
        txt = self.run_bzr_decode(['file-path', path], encoding='ascii')
325
362
 
326
363
    def test_revision_history(self):
327
 
        # TODO: jam 20060106 We don't support non-ascii revision ids yet, 
 
364
        # TODO: jam 20060106 We don't support non-ascii revision ids yet,
328
365
        #       so there is nothing which would fail in ascii encoding
329
366
        txt = self.run_bzr_decode('revision-history')
330
367
 
331
368
    def test_ancestry(self):
332
 
        # TODO: jam 20060106 We don't support non-ascii revision ids yet, 
 
369
        # TODO: jam 20060106 We don't support non-ascii revision ids yet,
333
370
        #       so there is nothing which would fail in ascii encoding
334
371
        txt = self.run_bzr_decode('ancestry')
335
372
 
336
373
    def test_diff(self):
337
 
        # TODO: jam 20060106 diff is a difficult one to test, because it 
 
374
        self._check_OSX_can_roundtrip(self.info['filename'])
 
375
        # TODO: jam 20060106 diff is a difficult one to test, because it
338
376
        #       shouldn't encode the file contents, but it needs some sort
339
377
        #       of encoding for the paths, etc which are displayed.
340
378
        self.build_tree_contents([(self.info['filename'], 'newline\n')])
341
379
        txt = self.run_bzr('diff', retcode=1)[0]
342
380
 
343
381
    def test_deleted(self):
 
382
        self._check_OSX_can_roundtrip(self.info['filename'])
344
383
        fname = self.info['filename']
345
384
        os.remove(fname)
346
385
        self.wt.remove(fname)
361
400
        self.build_tree_contents([(fname, 'modified\n')])
362
401
 
363
402
        txt = self.run_bzr_decode('modified')
 
403
        self._check_OSX_can_roundtrip(self.info['filename'])
364
404
        self.assertEqual('"'+fname+'"'+'\n', txt)
365
405
 
366
406
        self.run_bzr_decode('modified', encoding='ascii', fail=True)
396
436
        self.assertNotEqual(-1, txt.find(self.info['message']))
397
437
 
398
438
        txt = self.run_bzr_decode('log --verbose')
 
439
        # FIXME: iso-8859-2 test shouldn't be skipped here --vila 20090702
 
440
        self._check_OSX_can_roundtrip(self.info['filename'])
399
441
        self.assertNotEqual(-1, txt.find(fname))
400
442
 
401
443
        # Make sure log doesn't fail even if we can't write out
406
448
    def test_touching_revisions(self):
407
449
        fname = self.info['filename']
408
450
        txt = self.run_bzr_decode(['touching-revisions', fname])
 
451
        self._check_OSX_can_roundtrip(self.info['filename'])
409
452
        self.assertEqual(u'     3 added %s\n' % (fname,), txt)
410
453
 
411
454
        fname2 = self.info['filename'] + '2'
413
456
        self.wt.commit(u'Renamed %s => %s' % (fname, fname2))
414
457
 
415
458
        txt = self.run_bzr_decode(['touching-revisions', fname2])
416
 
        expected_txt = (u'     3 added %s\n' 
 
459
        expected_txt = (u'     3 added %s\n'
417
460
                        u'     4 renamed %s => %s\n'
418
461
                        % (fname, fname, fname2))
419
462
        self.assertEqual(expected_txt, txt)
436
479
        fname = self.info['filename'] + '2'
437
480
        self.build_tree_contents([(fname, 'unknown\n')])
438
481
 
439
 
        # TODO: jam 20060112 bzr unknowns is the only one which 
 
482
        # TODO: jam 20060112 bzr unknowns is the only one which
440
483
        #       quotes paths do we really want it to?
441
484
        #       awilkins 20080521 added and modified do it now as well
442
485
        txt = self.run_bzr_decode('unknowns')
 
486
        self._check_OSX_can_roundtrip(self.info['filename'])
443
487
        self.assertEqual(u'"%s"\n' % (fname,), txt)
444
488
 
445
489
        self.run_bzr_decode('unknowns', encoding='ascii', fail=True)
451
495
        def check_unknowns(expected):
452
496
            self.assertEqual(expected, list(self.wt.unknowns()))
453
497
 
 
498
        self._check_OSX_can_roundtrip(self.info['filename'])
454
499
        check_unknowns([fname2])
455
500
 
456
501
        self.run_bzr_decode(['ignore', './' + fname2])