1
# Copyright (C) 2005 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
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
17
"""Tests for the urlutils wrapper."""
23
from bzrlib import osutils, urlutils, win32utils
25
from bzrlib.errors import InvalidURL, InvalidURLJoin
26
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
29
class TestUrlToPath(TestCase):
31
def test_basename(self):
32
# bzrlib.urlutils.basename
33
# Test bzrlib.urlutils.split()
34
basename = urlutils.basename
35
if sys.platform == 'win32':
36
self.assertRaises(InvalidURL, basename, 'file:///path/to/foo')
37
self.assertEqual('foo', basename('file:///C|/foo'))
38
self.assertEqual('foo', basename('file:///C:/foo'))
39
self.assertEqual('', basename('file:///C:/'))
41
self.assertEqual('foo', basename('file:///foo'))
42
self.assertEqual('', basename('file:///'))
44
self.assertEqual('foo', basename('http://host/path/to/foo'))
45
self.assertEqual('foo', basename('http://host/path/to/foo/'))
47
basename('http://host/path/to/foo/', exclude_trailing_slash=False))
48
self.assertEqual('path', basename('http://host/path'))
49
self.assertEqual('', basename('http://host/'))
50
self.assertEqual('', basename('http://host'))
51
self.assertEqual('path', basename('http:///nohost/path'))
53
self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path'))
54
self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path/'))
55
self.assertEqual('', basename('random+scheme://user:pass@ahost:port/'))
58
self.assertEqual('foo', basename('path/to/foo'))
59
self.assertEqual('foo', basename('path/to/foo/'))
60
self.assertEqual('', basename('path/to/foo/',
61
exclude_trailing_slash=False))
62
self.assertEqual('foo', basename('path/../foo'))
63
self.assertEqual('foo', basename('../path/foo'))
65
def test_normalize_url_files(self):
66
# Test that local paths are properly normalized
67
normalize_url = urlutils.normalize_url
69
def norm_file(expected, path):
70
url = normalize_url(path)
71
self.assertStartsWith(url, 'file:///')
72
if sys.platform == 'win32':
73
url = url[len('file:///C:'):]
75
url = url[len('file://'):]
77
self.assertEndsWith(url, expected)
79
norm_file('path/to/foo', 'path/to/foo')
80
norm_file('/path/to/foo', '/path/to/foo')
81
norm_file('path/to/foo', '../path/to/foo')
83
# Local paths are assumed to *not* be escaped at all
85
u'uni/\xb5'.encode(bzrlib.user_encoding)
87
# locale cannot handle unicode
90
norm_file('uni/%C2%B5', u'uni/\xb5')
92
norm_file('uni/%25C2%25B5', u'uni/%C2%B5')
93
norm_file('uni/%20b', u'uni/ b')
94
# All the crazy characters get escaped in local paths => file:/// urls
95
# The ' ' character must not be at the end, because on win32
96
# it gets stripped off by ntpath.abspath
97
norm_file('%27%20%3B/%3F%3A%40%26%3D%2B%24%2C%23', "' ;/?:@&=+$,#")
99
def test_normalize_url_hybrid(self):
100
# Anything with a scheme:// should be treated as a hybrid url
101
# which changes what characters get escaped.
102
normalize_url = urlutils.normalize_url
104
eq = self.assertEqual
105
eq('file:///foo/', normalize_url(u'file:///foo/'))
106
eq('file:///foo/%20', normalize_url(u'file:///foo/ '))
107
eq('file:///foo/%20', normalize_url(u'file:///foo/%20'))
108
# Don't escape reserved characters
109
eq('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$',
110
normalize_url('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
111
eq('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$',
112
normalize_url('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
114
# Escape unicode characters, but not already escaped chars
115
eq('http://host/ab/%C2%B5/%C2%B5',
116
normalize_url(u'http://host/ab/%C2%B5/\xb5'))
118
# Normalize verifies URLs when they are not unicode
119
# (indicating they did not come from the user)
120
self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
121
self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
123
def test_url_scheme_re(self):
124
# Test paths that may be URLs
125
def test_one(url, scheme_and_path):
126
"""Assert that _url_scheme_re correctly matches
128
:param scheme_and_path: The (scheme, path) that should be matched
129
can be None, to indicate it should not match
131
m = urlutils._url_scheme_re.match(url)
132
if scheme_and_path is None:
133
self.assertEqual(None, m)
135
self.assertEqual(scheme_and_path[0], m.group('scheme'))
136
self.assertEqual(scheme_and_path[1], m.group('path'))
139
test_one('/path', None)
140
test_one('C:/path', None)
141
test_one('../path/to/foo', None)
142
test_one(u'../path/to/fo\xe5', None)
145
test_one('http://host/path/', ('http', 'host/path/'))
146
test_one('sftp://host/path/to/foo', ('sftp', 'host/path/to/foo'))
147
test_one('file:///usr/bin', ('file', '/usr/bin'))
148
test_one('file:///C:/Windows', ('file', '/C:/Windows'))
149
test_one('file:///C|/Windows', ('file', '/C|/Windows'))
150
test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
153
# Can't have slashes or colons in the scheme
154
test_one('/path/to/://foo', None)
155
test_one('path:path://foo', None)
156
# Must have more than one character for scheme
157
test_one('C://foo', None)
158
test_one('ab://foo', ('ab', 'foo'))
160
def test_dirname(self):
161
# Test bzrlib.urlutils.dirname()
162
dirname = urlutils.dirname
163
if sys.platform == 'win32':
164
self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
165
self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
166
self.assertEqual('file:///C|/', dirname('file:///C|/'))
168
self.assertEqual('file:///', dirname('file:///foo'))
169
self.assertEqual('file:///', dirname('file:///'))
171
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
172
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
173
self.assertEqual('http://host/path/to/foo',
174
dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
175
self.assertEqual('http://host/', dirname('http://host/path'))
176
self.assertEqual('http://host/', dirname('http://host/'))
177
self.assertEqual('http://host', dirname('http://host'))
178
self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
180
self.assertEqual('random+scheme://user:pass@ahost:port/',
181
dirname('random+scheme://user:pass@ahost:port/path'))
182
self.assertEqual('random+scheme://user:pass@ahost:port/',
183
dirname('random+scheme://user:pass@ahost:port/path/'))
184
self.assertEqual('random+scheme://user:pass@ahost:port/',
185
dirname('random+scheme://user:pass@ahost:port/'))
188
self.assertEqual('path/to', dirname('path/to/foo'))
189
self.assertEqual('path/to', dirname('path/to/foo/'))
190
self.assertEqual('path/to/foo',
191
dirname('path/to/foo/', exclude_trailing_slash=False))
192
self.assertEqual('path/..', dirname('path/../foo'))
193
self.assertEqual('../path', dirname('../path/foo'))
196
def test(expected, *args):
197
joined = urlutils.join(*args)
198
self.assertEqual(expected, joined)
200
# Test a single element
203
# Test relative path joining
204
test('foo/bar', 'foo', 'bar')
205
test('http://foo/bar', 'http://foo', 'bar')
206
test('http://foo/bar', 'http://foo', '.', 'bar')
207
test('http://foo/baz', 'http://foo', 'bar', '../baz')
208
test('http://foo/bar/baz', 'http://foo', 'bar/baz')
209
test('http://foo/baz', 'http://foo', 'bar/../baz')
212
test('http://bar', 'http://foo', 'http://bar')
213
test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
214
test('file:///bar', 'foo', 'file:///bar')
217
test('file:///foo', 'file:///', 'foo')
218
test('file:///bar/foo', 'file:///bar/', 'foo')
219
test('http://host/foo', 'http://host/', 'foo')
220
test('http://host/', 'http://host', '')
223
# Cannot go above root
224
self.assertRaises(InvalidURLJoin, urlutils.join,
225
'http://foo', '../baz')
226
self.assertRaises(InvalidURLJoin, urlutils.join,
229
def test_joinpath(self):
230
def test(expected, *args):
231
joined = urlutils.joinpath(*args)
232
self.assertEqual(expected, joined)
234
# Test a single element
237
# Test relative path joining
238
test('foo/bar', 'foo', 'bar')
239
test('foo/bar', 'foo', '.', 'bar')
240
test('foo/baz', 'foo', 'bar', '../baz')
241
test('foo/bar/baz', 'foo', 'bar/baz')
242
test('foo/baz', 'foo', 'bar/../baz')
244
# Test joining to an absolute path
246
test('/foo', '/foo', '.')
247
test('/foo/bar', '/foo', 'bar')
248
test('/', '/foo', '..')
250
# Test joining with an absolute path
251
test('/bar', 'foo', '/bar')
253
# Test joining to a path with a trailing slash
254
test('foo/bar', 'foo/', 'bar')
257
# Cannot go above root
258
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
259
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
260
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
262
def test_function_type(self):
263
if sys.platform == 'win32':
264
self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
265
self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
267
self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
268
self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
270
def test_posix_local_path_to_url(self):
271
to_url = urlutils._posix_local_path_to_url
272
self.assertEqual('file:///path/to/foo',
273
to_url('/path/to/foo'))
276
result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
278
raise TestSkipped("local encoding cannot handle unicode")
280
self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
282
def test_posix_local_path_from_url(self):
283
from_url = urlutils._posix_local_path_from_url
284
self.assertEqual('/path/to/foo',
285
from_url('file:///path/to/foo'))
286
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
287
from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
288
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
289
from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
291
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
293
def test_win32_local_path_to_url(self):
294
to_url = urlutils._win32_local_path_to_url
295
self.assertEqual('file:///C:/path/to/foo',
296
to_url('C:/path/to/foo'))
297
# BOGUS: on win32, ntpath.abspath will strip trailing
298
# whitespace, so this will always fail
299
# Though under linux, it fakes abspath support
300
# and thus will succeed
301
# self.assertEqual('file:///C:/path/to/foo%20',
302
# to_url('C:/path/to/foo '))
303
self.assertEqual('file:///C:/path/to/f%20oo',
304
to_url('C:/path/to/f oo'))
307
result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
309
raise TestSkipped("local encoding cannot handle unicode")
311
self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
313
def test_win32_unc_path_to_url(self):
314
to_url = urlutils._win32_local_path_to_url
315
self.assertEqual('file://HOST/path',
316
to_url(r'\\HOST\path'))
317
self.assertEqual('file://HOST/path',
318
to_url('//HOST/path'))
321
result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
323
raise TestSkipped("local encoding cannot handle unicode")
325
self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
328
def test_win32_local_path_from_url(self):
329
from_url = urlutils._win32_local_path_from_url
330
self.assertEqual('C:/path/to/foo',
331
from_url('file:///C|/path/to/foo'))
332
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
333
from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
334
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
335
from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
337
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
338
# Not a valid _win32 url, no drive letter
339
self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
341
def test_win32_unc_path_from_url(self):
342
from_url = urlutils._win32_local_path_from_url
343
self.assertEqual('//HOST/path', from_url('file://HOST/path'))
344
# despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
345
# we want to use only 2 slashes
346
# Firefox understand only 5 slashes in URL, but it's ugly
347
self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
348
self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
349
self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
350
# check for file://C:/ instead of file:///C:/
351
self.assertRaises(InvalidURL, from_url, 'file://C:/path')
353
def test_win32_extract_drive_letter(self):
354
extract = urlutils._win32_extract_drive_letter
355
self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
356
self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
357
self.assertRaises(InvalidURL, extract, 'file://', '/path')
359
def test_split(self):
360
# Test bzrlib.urlutils.split()
361
split = urlutils.split
362
if sys.platform == 'win32':
363
self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
364
self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
365
self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
367
self.assertEqual(('file:///', 'foo'), split('file:///foo'))
368
self.assertEqual(('file:///', ''), split('file:///'))
370
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
371
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
372
self.assertEqual(('http://host/path/to/foo', ''),
373
split('http://host/path/to/foo/', exclude_trailing_slash=False))
374
self.assertEqual(('http://host/', 'path'), split('http://host/path'))
375
self.assertEqual(('http://host/', ''), split('http://host/'))
376
self.assertEqual(('http://host', ''), split('http://host'))
377
self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
379
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
380
split('random+scheme://user:pass@ahost:port/path'))
381
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
382
split('random+scheme://user:pass@ahost:port/path/'))
383
self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
384
split('random+scheme://user:pass@ahost:port/'))
387
self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
388
self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
389
self.assertEqual(('path/to/foo', ''),
390
split('path/to/foo/', exclude_trailing_slash=False))
391
self.assertEqual(('path/..', 'foo'), split('path/../foo'))
392
self.assertEqual(('../path', 'foo'), split('../path/foo'))
394
def test_win32_strip_local_trailing_slash(self):
395
strip = urlutils._win32_strip_local_trailing_slash
396
self.assertEqual('file://', strip('file://'))
397
self.assertEqual('file:///', strip('file:///'))
398
self.assertEqual('file:///C', strip('file:///C'))
399
self.assertEqual('file:///C:', strip('file:///C:'))
400
self.assertEqual('file:///d|', strip('file:///d|'))
401
self.assertEqual('file:///C:/', strip('file:///C:/'))
402
self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
404
def test_strip_trailing_slash(self):
405
sts = urlutils.strip_trailing_slash
406
if sys.platform == 'win32':
407
self.assertEqual('file:///C|/', sts('file:///C|/'))
408
self.assertEqual('file:///C:/foo', sts('file:///C:/foo'))
409
self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
411
self.assertEqual('file:///', sts('file:///'))
412
self.assertEqual('file:///foo', sts('file:///foo'))
413
self.assertEqual('file:///foo', sts('file:///foo/'))
415
self.assertEqual('http://host/', sts('http://host/'))
416
self.assertEqual('http://host/foo', sts('http://host/foo'))
417
self.assertEqual('http://host/foo', sts('http://host/foo/'))
419
# No need to fail just because the slash is missing
420
self.assertEqual('http://host', sts('http://host'))
421
# TODO: jam 20060502 Should this raise InvalidURL?
422
self.assertEqual('file://', sts('file://'))
424
self.assertEqual('random+scheme://user:pass@ahost:port/path',
425
sts('random+scheme://user:pass@ahost:port/path'))
426
self.assertEqual('random+scheme://user:pass@ahost:port/path',
427
sts('random+scheme://user:pass@ahost:port/path/'))
428
self.assertEqual('random+scheme://user:pass@ahost:port/',
429
sts('random+scheme://user:pass@ahost:port/'))
431
# Make sure relative paths work too
432
self.assertEqual('path/to/foo', sts('path/to/foo'))
433
self.assertEqual('path/to/foo', sts('path/to/foo/'))
434
self.assertEqual('../to/foo', sts('../to/foo/'))
435
self.assertEqual('path/../foo', sts('path/../foo/'))
437
def test_unescape_for_display_utf8(self):
438
# Test that URLs are converted to nice unicode strings for display
439
def test(expected, url, encoding='utf-8'):
440
disp_url = urlutils.unescape_for_display(url, encoding=encoding)
441
self.assertIsInstance(disp_url, unicode)
442
self.assertEqual(expected, disp_url)
444
test('http://foo', 'http://foo')
445
if sys.platform == 'win32':
446
test('C:/foo/path', 'file:///C|/foo/path')
447
test('C:/foo/path', 'file:///C:/foo/path')
449
test('/foo/path', 'file:///foo/path')
451
test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
452
test(u'http://host/r\xe4ksm\xf6rg\xe5s',
453
'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
455
# Make sure special escaped characters stay escaped
456
test(u'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23',
457
'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23')
459
# Can we handle sections that don't have utf-8 encoding?
460
test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
461
'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s')
463
# Test encoding into output that can handle some characters
464
test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
465
'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
466
encoding='iso-8859-1')
468
# This one can be encoded into utf8
469
test(u'http://host/\u062c\u0648\u062c\u0648',
470
'http://host/%d8%ac%d9%88%d8%ac%d9%88',
473
# This can't be put into 8859-1 and so stays as escapes
474
test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
475
'http://host/%d8%ac%d9%88%d8%ac%d9%88',
476
encoding='iso-8859-1')
478
def test_escape(self):
479
self.assertEqual('%25', urlutils.escape('%'))
480
self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
482
def test_unescape(self):
483
self.assertEqual('%', urlutils.unescape('%25'))
484
self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
486
self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
487
self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
488
self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
490
def test_escape_unescape(self):
491
self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
492
self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
494
def test_relative_url(self):
495
def test(expected, base, other):
496
result = urlutils.relative_url(base, other)
497
self.assertEqual(expected, result)
499
test('a', 'http://host/', 'http://host/a')
500
test('http://entirely/different', 'sftp://host/branch',
501
'http://entirely/different')
502
test('../person/feature', 'http://host/branch/mainline',
503
'http://host/branch/person/feature')
504
test('..', 'http://host/branch', 'http://host/')
505
test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
506
test('.', 'http://host1/branch', 'http://host1/branch')
507
test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
508
'file:///home/jelmer/branch/2b')
509
test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
510
'sftp://host/home/jelmer/branch/2b')
511
test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
512
'http://host/home/jelmer/branch/feature/%2b')
513
test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
514
'http://host/home/jelmer/branch/feature/2b')
515
# relative_url should preserve a trailing slash
516
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
517
'http://host/home/jelmer/branch/feature/2b/')
518
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
519
'http://host/home/jelmer/branch/feature/2b/')
521
# TODO: treat http://host as http://host/
522
# relative_url is typically called from a branch.base or
523
# transport.base which always ends with a /
524
#test('a', 'http://host', 'http://host/a')
525
test('http://host/a', 'http://host', 'http://host/a')
526
#test('.', 'http://host', 'http://host/')
527
test('http://host/', 'http://host', 'http://host/')
528
#test('.', 'http://host/', 'http://host')
529
test('http://host', 'http://host/', 'http://host')
532
class TestCwdToURL(TestCaseInTempDir):
533
"""Test that local_path_to_url works base on the cwd"""
536
# This test will fail if getcwd is not ascii
540
url = urlutils.local_path_to_url('.')
541
self.assertEndsWith(url, '/mytest')
543
def test_non_ascii(self):
544
if win32utils.winver == 'Windows 98':
545
raise TestSkipped('Windows 98 cannot handle unicode filenames')
550
raise TestSkipped('cannot create unicode directory')
554
# On Mac OSX this directory is actually:
555
# u'/dode\u0301' => '/dode\xcc\x81
556
# but we should normalize it back to
557
# u'/dod\xe9' => '/dod\xc3\xa9'
558
url = urlutils.local_path_to_url('.')
559
self.assertEndsWith(url, '/dod%C3%A9')