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
23
from bzrlib.tests import TestCaseWithTransport, TestSkipped
24
from bzrlib.trace import mutter, note
27
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):
28
37
"""Test that bzr handles files/committers/etc which are non-ascii."""
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()
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())
41
if self._orig_email is not None:
42
os.environ['BZR_EMAIL'] = self._orig_email
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()
49
50
def run_bzr_decode(self, args, encoding=None, fail=False, retcode=None,
51
52
"""Run bzr and decode the output into a particular encoding.
53
54
Returns a string containing the stdout output from bzr.
55
:param fail: If true, the operation is expected to fail with
56
:param fail: If true, the operation is expected to fail with
58
59
if encoding is None:
59
60
encoding = osutils.get_user_encoding()
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:
73
75
self.fail("Expected UnicodeError not raised")
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.
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.
87
fs_enc = osutils._fs_enc
88
if sys.platform == 'darwin':
89
encoded = path.encode(fs_enc)
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"'
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']
82
106
thing.encode(fs_enc)
83
107
except UnicodeEncodeError:
84
raise TestSkipped(('Unable to represent path %r'
85
' in filesystem encoding "%s"')
108
raise tests.TestSkipped(
109
'Unable to represent path %r in filesystem encoding "%s"'
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))
119
def create_base(self):
96
120
wt = self.make_branch_and_tree('.')
97
121
self.build_tree_contents([('a', 'foo\n')])
104
128
wt.commit(self.info['message'])
130
fname = self.info['filename']
106
131
self.build_tree_contents([(fname, 'unicode filename\n')])
108
133
wt.commit(u'And a unicode file\n')
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
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)
117
148
txt = self.run_bzr_decode('status', encoding='ascii')
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
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])
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')
319
356
txt = self.run_bzr_decode(['file-path', path])
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')
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')
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')
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]
343
381
def test_deleted(self):
382
self._check_OSX_can_roundtrip(self.info['filename'])
344
383
fname = self.info['filename']
346
385
self.wt.remove(fname)
436
479
fname = self.info['filename'] + '2'
437
480
self.build_tree_contents([(fname, 'unknown\n')])
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)
445
489
self.run_bzr_decode('unknowns', encoding='ascii', fail=True)