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
17
17
"""Black-box tests for bzr handling non-ascii characters."""
22
from bzrlib import osutils, urlutils
24
from bzrlib.tests import TestCaseWithTransport, TestSkipped
25
from bzrlib.trace import mutter, note
28
class TestNonAscii(TestCaseWithTransport):
27
from bzrlib.tests import EncodingAdapter
30
def load_tests(standard_tests, module, loader):
31
return tests.multiply_tests(standard_tests,
32
EncodingAdapter.encoding_scenarios,
36
class TestNonAscii(tests.TestCaseWithTransport):
29
37
"""Test that bzr handles files/committers/etc which are non-ascii."""
32
40
super(TestNonAscii, self).setUp()
33
self._orig_email = os.environ.get('BZR_EMAIL', None)
34
self._orig_encoding = bzrlib.user_encoding
41
self._check_can_encode_paths()
36
bzrlib.user_encoding = self.encoding
43
self.overrideAttr(osutils, '_cached_user_encoding', self.encoding)
37
44
email = self.info['committer'] + ' <joe@foo.com>'
38
os.environ['BZR_EMAIL'] = email.encode(bzrlib.user_encoding)
45
os.environ['BZR_EMAIL'] = email.encode(osutils.get_user_encoding())
42
if self._orig_email is not None:
43
os.environ['BZR_EMAIL'] = self._orig_email
45
if os.environ.get('BZR_EMAIL', None) is not None:
46
del os.environ['BZR_EMAIL']
47
bzrlib.user_encoding = self._orig_encoding
48
super(TestNonAscii, self).tearDown()
50
48
def run_bzr_decode(self, args, encoding=None, fail=False, retcode=None,
52
50
"""Run bzr and decode the output into a particular encoding.
54
52
Returns a string containing the stdout output from bzr.
56
:param fail: If true, the operation is expected to fail with
54
:param fail: If true, the operation is expected to fail with
59
57
if encoding is None:
60
encoding = bzrlib.user_encoding
58
encoding = osutils.get_user_encoding()
62
out = self.run_bzr(args, output_encoding=encoding, encoding=encoding,
63
retcode=retcode, working_dir=working_dir)[0]
60
out = self.run_bzr(args,
61
output_encoding=encoding, encoding=encoding,
62
retcode=retcode, working_dir=working_dir)[0]
64
63
return out.decode(encoding)
65
64
except UnicodeError, e:
74
73
self.fail("Expected UnicodeError not raised")
76
def create_base(self):
77
fs_enc = sys.getfilesystemencoding()
75
def _check_OSX_can_roundtrip(self, path, fs_enc=None):
76
"""Stop the test if it's about to fail or errors out.
78
Until we get proper support on OSX for accented paths (in fact, any
79
path whose NFD decomposition is different than the NFC one), this is
80
the best way to keep test active (as opposed to disabling them
81
completely). This is a stop gap. The tests should at least be rewritten
82
so that the failing ones are clearly separated from the passing ones.
85
fs_enc = osutils._fs_enc
86
if sys.platform == 'darwin':
87
encoded = path.encode(fs_enc)
89
normal_thing = unicodedata.normalize('NFD', path)
90
mac_encoded = normal_thing.encode(fs_enc)
91
if mac_encoded != encoded:
92
raise tests.KnownFailure(
93
'Unable to roundtrip path %r on OSX filesystem'
94
' using encoding "%s"'
97
def _check_can_encode_paths(self):
98
fs_enc = osutils._fs_enc
78
99
terminal_enc = osutils.get_terminal_encoding()
79
100
fname = self.info['filename']
80
101
dir_name = self.info['directory']
83
104
thing.encode(fs_enc)
84
105
except UnicodeEncodeError:
85
raise TestSkipped(('Unable to represent path %r'
86
' in filesystem encoding "%s"')
106
raise tests.TestSkipped(
107
'Unable to represent path %r in filesystem encoding "%s"'
89
110
thing.encode(terminal_enc)
90
111
except UnicodeEncodeError:
91
raise TestSkipped(('Unable to represent path %r'
92
' in terminal encoding "%s"'
93
' (even though it is valid in'
94
' filesystem encoding "%s")')
95
% (thing, terminal_enc, fs_enc))
112
raise tests.TestSkipped(
113
'Unable to represent path %r in terminal encoding "%s"'
114
' (even though it is valid in filesystem encoding "%s")'
115
% (thing, terminal_enc, fs_enc))
117
def create_base(self):
97
118
wt = self.make_branch_and_tree('.')
98
119
self.build_tree_contents([('a', 'foo\n')])
105
126
wt.commit(self.info['message'])
128
fname = self.info['filename']
107
129
self.build_tree_contents([(fname, 'unicode filename\n')])
109
131
wt.commit(u'And a unicode file\n')
133
# FIXME: We don't check that the add went well, in fact, it doesn't on
134
# OSX (when LC_ALL is set correctly) because the added path doesn't
135
# match the one used on OSX. But checking here will require more
136
# invasive changes than adding the _check_OSX_can_roundtrip(), so I
137
# punt for now -- vila 20090702
112
139
def test_status(self):
113
140
self.build_tree_contents(
114
141
[(self.info['filename'], 'changed something\n')])
115
142
txt = self.run_bzr_decode('status')
143
self._check_OSX_can_roundtrip(self.info['filename'])
116
144
self.assertEqual(u'modified:\n %s\n' % (self.info['filename'],), txt)
118
146
txt = self.run_bzr_decode('status', encoding='ascii')
252
283
# TODO: jam 20060427 For drastically improving performance, we probably
253
284
# could create a local repository, so it wouldn't have to copy
254
285
# the files around as much.
286
# Note that the tests don't actually fail, but if we don't set this
287
# flag, we end up getting "Lock was not Unlocked" warnings
256
289
dirname = self.info['directory']
257
290
self.run_bzr_decode(['push', dirname])
299
332
fname = self.info['filename']
300
333
txt = self.run_bzr_decode(['file-id', fname])
302
# TODO: jam 20060106 We don't support non-ascii file ids yet,
335
# TODO: jam 20060106 We don't support non-ascii file ids yet,
303
336
# so there is nothing which would fail in ascii encoding
304
337
# This *should* be retcode=3
305
338
txt = self.run_bzr_decode(['file-id', fname], encoding='ascii')
314
347
self.wt.add('base')
315
348
self.wt.add('base/'+dirname)
316
349
path = osutils.pathjoin('base', dirname, fname)
350
self._check_OSX_can_roundtrip(self.info['filename'])
317
351
self.wt.rename_one(fname, path)
318
352
self.wt.commit('moving things around')
320
354
txt = self.run_bzr_decode(['file-path', path])
322
# TODO: jam 20060106 We don't support non-ascii file ids yet,
356
# TODO: jam 20060106 We don't support non-ascii file ids yet,
323
357
# so there is nothing which would fail in ascii encoding
324
358
# This *should* be retcode=3
325
359
txt = self.run_bzr_decode(['file-path', path], encoding='ascii')
327
361
def test_revision_history(self):
328
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
362
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
329
363
# so there is nothing which would fail in ascii encoding
330
364
txt = self.run_bzr_decode('revision-history')
332
366
def test_ancestry(self):
333
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
367
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
334
368
# so there is nothing which would fail in ascii encoding
335
369
txt = self.run_bzr_decode('ancestry')
337
371
def test_diff(self):
338
# TODO: jam 20060106 diff is a difficult one to test, because it
372
self._check_OSX_can_roundtrip(self.info['filename'])
373
# TODO: jam 20060106 diff is a difficult one to test, because it
339
374
# shouldn't encode the file contents, but it needs some sort
340
375
# of encoding for the paths, etc which are displayed.
341
376
self.build_tree_contents([(self.info['filename'], 'newline\n')])
342
377
txt = self.run_bzr('diff', retcode=1)[0]
344
379
def test_deleted(self):
380
self._check_OSX_can_roundtrip(self.info['filename'])
345
381
fname = self.info['filename']
347
383
self.wt.remove(fname)
437
477
fname = self.info['filename'] + '2'
438
478
self.build_tree_contents([(fname, 'unknown\n')])
440
# TODO: jam 20060112 bzr unknowns is the only one which
480
# TODO: jam 20060112 bzr unknowns is the only one which
441
481
# quotes paths do we really want it to?
442
482
# awilkins 20080521 added and modified do it now as well
443
483
txt = self.run_bzr_decode('unknowns')
484
self._check_OSX_can_roundtrip(self.info['filename'])
444
485
self.assertEqual(u'"%s"\n' % (fname,), txt)
446
487
self.run_bzr_decode('unknowns', encoding='ascii', fail=True)