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
# Unescape characters that don't need to be escaped
119
eq('http://host/~bob%2525-._',
120
normalize_url('http://host/%7Ebob%2525%2D%2E%5F'))
121
eq('http://host/~bob%2525-._',
122
normalize_url(u'http://host/%7Ebob%2525%2D%2E%5F'))
124
# Normalize verifies URLs when they are not unicode
125
# (indicating they did not come from the user)
126
self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
127
self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
129
def test_url_scheme_re(self):
130
# Test paths that may be URLs
131
def test_one(url, scheme_and_path):
132
"""Assert that _url_scheme_re correctly matches
134
:param scheme_and_path: The (scheme, path) that should be matched
135
can be None, to indicate it should not match
137
m = urlutils._url_scheme_re.match(url)
138
if scheme_and_path is None:
139
self.assertEqual(None, m)
141
self.assertEqual(scheme_and_path[0], m.group('scheme'))
142
self.assertEqual(scheme_and_path[1], m.group('path'))
145
test_one('/path', None)
146
test_one('C:/path', None)
147
test_one('../path/to/foo', None)
148
test_one(u'../path/to/fo\xe5', None)
151
test_one('http://host/path/', ('http', 'host/path/'))
152
test_one('sftp://host/path/to/foo', ('sftp', 'host/path/to/foo'))
153
test_one('file:///usr/bin', ('file', '/usr/bin'))
154
test_one('file:///C:/Windows', ('file', '/C:/Windows'))
155
test_one('file:///C|/Windows', ('file', '/C|/Windows'))
156
test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
159
# Can't have slashes or colons in the scheme
160
test_one('/path/to/://foo', None)
161
test_one('path:path://foo', None)
162
# Must have more than one character for scheme
163
test_one('C://foo', None)
164
test_one('ab://foo', ('ab', 'foo'))
166
def test_dirname(self):
167
# Test bzrlib.urlutils.dirname()
168
dirname = urlutils.dirname
169
if sys.platform == 'win32':
170
self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
171
self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
172
self.assertEqual('file:///C|/', dirname('file:///C|/'))
174
self.assertEqual('file:///', dirname('file:///foo'))
175
self.assertEqual('file:///', dirname('file:///'))
177
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
178
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
179
self.assertEqual('http://host/path/to/foo',
180
dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
181
self.assertEqual('http://host/', dirname('http://host/path'))
182
self.assertEqual('http://host/', dirname('http://host/'))
183
self.assertEqual('http://host', dirname('http://host'))
184
self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
186
self.assertEqual('random+scheme://user:pass@ahost:port/',
187
dirname('random+scheme://user:pass@ahost:port/path'))
188
self.assertEqual('random+scheme://user:pass@ahost:port/',
189
dirname('random+scheme://user:pass@ahost:port/path/'))
190
self.assertEqual('random+scheme://user:pass@ahost:port/',
191
dirname('random+scheme://user:pass@ahost:port/'))
194
self.assertEqual('path/to', dirname('path/to/foo'))
195
self.assertEqual('path/to', dirname('path/to/foo/'))
196
self.assertEqual('path/to/foo',
197
dirname('path/to/foo/', exclude_trailing_slash=False))
198
self.assertEqual('path/..', dirname('path/../foo'))
199
self.assertEqual('../path', dirname('../path/foo'))
202
def test(expected, *args):
203
joined = urlutils.join(*args)
204
self.assertEqual(expected, joined)
206
# Test relative path joining
207
test('foo', 'foo') # relative fragment with nothing is preserved.
208
test('foo/bar', 'foo', 'bar')
209
test('http://foo/bar', 'http://foo', 'bar')
210
test('http://foo/bar', 'http://foo', '.', 'bar')
211
test('http://foo/baz', 'http://foo', 'bar', '../baz')
212
test('http://foo/bar/baz', 'http://foo', 'bar/baz')
213
test('http://foo/baz', 'http://foo', 'bar/../baz')
214
test('http://foo/baz', 'http://foo/bar/', '../baz')
217
test('http://foo', 'http://foo') # abs url with nothing is preserved.
218
test('http://bar', 'http://foo', 'http://bar')
219
test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
220
test('file:///bar', 'foo', 'file:///bar')
221
test('http://bar/', 'http://foo', 'http://bar/')
222
test('http://bar/a', 'http://foo', 'http://bar/a')
223
test('http://bar/a/', 'http://foo', 'http://bar/a/')
226
test('file:///foo', 'file:///', 'foo')
227
test('file:///bar/foo', 'file:///bar/', 'foo')
228
test('http://host/foo', 'http://host/', 'foo')
229
test('http://host/', 'http://host', '')
232
# Cannot go above root
233
# Implicitly at root:
234
self.assertRaises(InvalidURLJoin, urlutils.join,
235
'http://foo', '../baz')
236
self.assertRaises(InvalidURLJoin, urlutils.join,
238
# Joining from a path explicitly under the root.
239
self.assertRaises(InvalidURLJoin, urlutils.join,
240
'http://foo/a', '../../b')
242
def test_joinpath(self):
243
def test(expected, *args):
244
joined = urlutils.joinpath(*args)
245
self.assertEqual(expected, joined)
247
# Test a single element
250
# Test relative path joining
251
test('foo/bar', 'foo', 'bar')
252
test('foo/bar', 'foo', '.', 'bar')
253
test('foo/baz', 'foo', 'bar', '../baz')
254
test('foo/bar/baz', 'foo', 'bar/baz')
255
test('foo/baz', 'foo', 'bar/../baz')
257
# Test joining to an absolute path
259
test('/foo', '/foo', '.')
260
test('/foo/bar', '/foo', 'bar')
261
test('/', '/foo', '..')
263
# Test joining with an absolute path
264
test('/bar', 'foo', '/bar')
266
# Test joining to a path with a trailing slash
267
test('foo/bar', 'foo/', 'bar')
270
# Cannot go above root
271
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
272
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
273
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
275
def test_function_type(self):
276
if sys.platform == 'win32':
277
self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
278
self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
280
self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
281
self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
283
def test_posix_local_path_to_url(self):
284
to_url = urlutils._posix_local_path_to_url
285
self.assertEqual('file:///path/to/foo',
286
to_url('/path/to/foo'))
289
result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
291
raise TestSkipped("local encoding cannot handle unicode")
293
self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
295
def test_posix_local_path_from_url(self):
296
from_url = urlutils._posix_local_path_from_url
297
self.assertEqual('/path/to/foo',
298
from_url('file:///path/to/foo'))
299
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
300
from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
301
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
302
from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
304
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
306
def test_win32_local_path_to_url(self):
307
to_url = urlutils._win32_local_path_to_url
308
self.assertEqual('file:///C:/path/to/foo',
309
to_url('C:/path/to/foo'))
310
# BOGUS: on win32, ntpath.abspath will strip trailing
311
# whitespace, so this will always fail
312
# Though under linux, it fakes abspath support
313
# and thus will succeed
314
# self.assertEqual('file:///C:/path/to/foo%20',
315
# to_url('C:/path/to/foo '))
316
self.assertEqual('file:///C:/path/to/f%20oo',
317
to_url('C:/path/to/f oo'))
320
result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
322
raise TestSkipped("local encoding cannot handle unicode")
324
self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
326
def test_win32_unc_path_to_url(self):
327
to_url = urlutils._win32_local_path_to_url
328
self.assertEqual('file://HOST/path',
329
to_url(r'\\HOST\path'))
330
self.assertEqual('file://HOST/path',
331
to_url('//HOST/path'))
334
result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
336
raise TestSkipped("local encoding cannot handle unicode")
338
self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
341
def test_win32_local_path_from_url(self):
342
from_url = urlutils._win32_local_path_from_url
343
self.assertEqual('C:/path/to/foo',
344
from_url('file:///C|/path/to/foo'))
345
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
346
from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
347
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
348
from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
350
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
351
# Not a valid _win32 url, no drive letter
352
self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
354
def test_win32_unc_path_from_url(self):
355
from_url = urlutils._win32_local_path_from_url
356
self.assertEqual('//HOST/path', from_url('file://HOST/path'))
357
# despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
358
# we want to use only 2 slashes
359
# Firefox understand only 5 slashes in URL, but it's ugly
360
self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
361
self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
362
self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
363
# check for file://C:/ instead of file:///C:/
364
self.assertRaises(InvalidURL, from_url, 'file://C:/path')
366
def test_win32_extract_drive_letter(self):
367
extract = urlutils._win32_extract_drive_letter
368
self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
369
self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
370
self.assertRaises(InvalidURL, extract, 'file://', '/path')
372
def test_split(self):
373
# Test bzrlib.urlutils.split()
374
split = urlutils.split
375
if sys.platform == 'win32':
376
self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
377
self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
378
self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
380
self.assertEqual(('file:///', 'foo'), split('file:///foo'))
381
self.assertEqual(('file:///', ''), split('file:///'))
383
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
384
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
385
self.assertEqual(('http://host/path/to/foo', ''),
386
split('http://host/path/to/foo/', exclude_trailing_slash=False))
387
self.assertEqual(('http://host/', 'path'), split('http://host/path'))
388
self.assertEqual(('http://host/', ''), split('http://host/'))
389
self.assertEqual(('http://host', ''), split('http://host'))
390
self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
392
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
393
split('random+scheme://user:pass@ahost:port/path'))
394
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
395
split('random+scheme://user:pass@ahost:port/path/'))
396
self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
397
split('random+scheme://user:pass@ahost:port/'))
400
self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
401
self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
402
self.assertEqual(('path/to/foo', ''),
403
split('path/to/foo/', exclude_trailing_slash=False))
404
self.assertEqual(('path/..', 'foo'), split('path/../foo'))
405
self.assertEqual(('../path', 'foo'), split('../path/foo'))
407
def test_win32_strip_local_trailing_slash(self):
408
strip = urlutils._win32_strip_local_trailing_slash
409
self.assertEqual('file://', strip('file://'))
410
self.assertEqual('file:///', strip('file:///'))
411
self.assertEqual('file:///C', strip('file:///C'))
412
self.assertEqual('file:///C:', strip('file:///C:'))
413
self.assertEqual('file:///d|', strip('file:///d|'))
414
self.assertEqual('file:///C:/', strip('file:///C:/'))
415
self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
417
def test_strip_trailing_slash(self):
418
sts = urlutils.strip_trailing_slash
419
if sys.platform == 'win32':
420
self.assertEqual('file:///C|/', sts('file:///C|/'))
421
self.assertEqual('file:///C:/foo', sts('file:///C:/foo'))
422
self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
424
self.assertEqual('file:///', sts('file:///'))
425
self.assertEqual('file:///foo', sts('file:///foo'))
426
self.assertEqual('file:///foo', sts('file:///foo/'))
428
self.assertEqual('http://host/', sts('http://host/'))
429
self.assertEqual('http://host/foo', sts('http://host/foo'))
430
self.assertEqual('http://host/foo', sts('http://host/foo/'))
432
# No need to fail just because the slash is missing
433
self.assertEqual('http://host', sts('http://host'))
434
# TODO: jam 20060502 Should this raise InvalidURL?
435
self.assertEqual('file://', sts('file://'))
437
self.assertEqual('random+scheme://user:pass@ahost:port/path',
438
sts('random+scheme://user:pass@ahost:port/path'))
439
self.assertEqual('random+scheme://user:pass@ahost:port/path',
440
sts('random+scheme://user:pass@ahost:port/path/'))
441
self.assertEqual('random+scheme://user:pass@ahost:port/',
442
sts('random+scheme://user:pass@ahost:port/'))
444
# Make sure relative paths work too
445
self.assertEqual('path/to/foo', sts('path/to/foo'))
446
self.assertEqual('path/to/foo', sts('path/to/foo/'))
447
self.assertEqual('../to/foo', sts('../to/foo/'))
448
self.assertEqual('path/../foo', sts('path/../foo/'))
450
def test_unescape_for_display_utf8(self):
451
# Test that URLs are converted to nice unicode strings for display
452
def test(expected, url, encoding='utf-8'):
453
disp_url = urlutils.unescape_for_display(url, encoding=encoding)
454
self.assertIsInstance(disp_url, unicode)
455
self.assertEqual(expected, disp_url)
457
test('http://foo', 'http://foo')
458
if sys.platform == 'win32':
459
test('C:/foo/path', 'file:///C|/foo/path')
460
test('C:/foo/path', 'file:///C:/foo/path')
462
test('/foo/path', 'file:///foo/path')
464
test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
465
test(u'http://host/r\xe4ksm\xf6rg\xe5s',
466
'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
468
# Make sure special escaped characters stay escaped
469
test(u'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23',
470
'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23')
472
# Can we handle sections that don't have utf-8 encoding?
473
test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
474
'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s')
476
# Test encoding into output that can handle some characters
477
test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
478
'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
479
encoding='iso-8859-1')
481
# This one can be encoded into utf8
482
test(u'http://host/\u062c\u0648\u062c\u0648',
483
'http://host/%d8%ac%d9%88%d8%ac%d9%88',
486
# This can't be put into 8859-1 and so stays as escapes
487
test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
488
'http://host/%d8%ac%d9%88%d8%ac%d9%88',
489
encoding='iso-8859-1')
491
def test_escape(self):
492
self.assertEqual('%25', urlutils.escape('%'))
493
self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
495
def test_unescape(self):
496
self.assertEqual('%', urlutils.unescape('%25'))
497
self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
499
self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
500
self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
501
self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
503
def test_escape_unescape(self):
504
self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
505
self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
507
def test_relative_url(self):
508
def test(expected, base, other):
509
result = urlutils.relative_url(base, other)
510
self.assertEqual(expected, result)
512
test('a', 'http://host/', 'http://host/a')
513
test('http://entirely/different', 'sftp://host/branch',
514
'http://entirely/different')
515
test('../person/feature', 'http://host/branch/mainline',
516
'http://host/branch/person/feature')
517
test('..', 'http://host/branch', 'http://host/')
518
test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
519
test('.', 'http://host1/branch', 'http://host1/branch')
520
test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
521
'file:///home/jelmer/branch/2b')
522
test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
523
'sftp://host/home/jelmer/branch/2b')
524
test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
525
'http://host/home/jelmer/branch/feature/%2b')
526
test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
527
'http://host/home/jelmer/branch/feature/2b')
528
# relative_url should preserve a trailing slash
529
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
530
'http://host/home/jelmer/branch/feature/2b/')
531
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
532
'http://host/home/jelmer/branch/feature/2b/')
534
# TODO: treat http://host as http://host/
535
# relative_url is typically called from a branch.base or
536
# transport.base which always ends with a /
537
#test('a', 'http://host', 'http://host/a')
538
test('http://host/a', 'http://host', 'http://host/a')
539
#test('.', 'http://host', 'http://host/')
540
test('http://host/', 'http://host', 'http://host/')
541
#test('.', 'http://host/', 'http://host')
542
test('http://host', 'http://host/', 'http://host')
545
class TestCwdToURL(TestCaseInTempDir):
546
"""Test that local_path_to_url works base on the cwd"""
549
# This test will fail if getcwd is not ascii
553
url = urlutils.local_path_to_url('.')
554
self.assertEndsWith(url, '/mytest')
556
def test_non_ascii(self):
557
if win32utils.winver == 'Windows 98':
558
raise TestSkipped('Windows 98 cannot handle unicode filenames')
563
raise TestSkipped('cannot create unicode directory')
567
# On Mac OSX this directory is actually:
568
# u'/dode\u0301' => '/dode\xcc\x81
569
# but we should normalize it back to
570
# u'/dod\xe9' => '/dod\xc3\xa9'
571
url = urlutils.local_path_to_url('.')
572
self.assertEndsWith(url, '/dod%C3%A9')
575
class TestDeriveToLocation(TestCase):
576
"""Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
578
def test_to_locations_derived_from_paths(self):
579
derive = urlutils.derive_to_location
580
self.assertEqual("bar", derive("bar"))
581
self.assertEqual("bar", derive("../bar"))
582
self.assertEqual("bar", derive("/foo/bar"))
583
self.assertEqual("bar", derive("c:/foo/bar"))
584
self.assertEqual("bar", derive("c:bar"))
586
def test_to_locations_derived_from_urls(self):
587
derive = urlutils.derive_to_location
588
self.assertEqual("bar", derive("http://foo/bar"))
589
self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
590
self.assertEqual("foo-bar", derive("lp:foo-bar"))