267
296
# Invalid joinings
268
297
# Cannot go above root
269
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
270
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
271
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
298
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
300
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
302
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
305
def test_join_segment_parameters_raw(self):
306
join_segment_parameters_raw = urlutils.join_segment_parameters_raw
307
self.assertEqual("/somedir/path",
308
join_segment_parameters_raw("/somedir/path"))
309
self.assertEqual("/somedir/path,rawdata",
310
join_segment_parameters_raw("/somedir/path", "rawdata"))
311
self.assertRaises(urlutils.InvalidURLJoin,
312
join_segment_parameters_raw, "/somedir/path",
313
"rawdata1,rawdata2,rawdata3")
314
self.assertEqual("/somedir/path,bla,bar",
315
join_segment_parameters_raw("/somedir/path", "bla", "bar"))
316
self.assertEqual("/somedir,exist=some/path,bla,bar",
317
join_segment_parameters_raw("/somedir,exist=some/path",
319
self.assertRaises(TypeError, join_segment_parameters_raw,
322
def test_join_segment_parameters(self):
323
join_segment_parameters = urlutils.join_segment_parameters
324
self.assertEqual("/somedir/path",
325
join_segment_parameters("/somedir/path", {}))
326
self.assertEqual("/somedir/path,key1=val1",
327
join_segment_parameters("/somedir/path", {"key1": "val1"}))
328
self.assertRaises(urlutils.InvalidURLJoin,
329
join_segment_parameters, "/somedir/path",
330
{"branch": "brr,brr,brr"})
331
self.assertRaises(urlutils.InvalidURLJoin,
332
join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
333
self.assertEqual("/somedir/path,key1=val1,key2=val2",
334
join_segment_parameters("/somedir/path", {
335
"key1": "val1", "key2": "val2"}))
336
self.assertEqual("/somedir/path,key1=val1,key2=val2",
337
join_segment_parameters("/somedir/path,key1=val1", {
339
self.assertEqual("/somedir/path,key1=val2",
340
join_segment_parameters("/somedir/path,key1=val1", {
342
self.assertEqual("/somedir,exist=some/path,key1=val1",
343
join_segment_parameters("/somedir,exist=some/path",
345
self.assertEqual("/,key1=val1,key2=val2",
346
join_segment_parameters("/,key1=val1", {"key2": "val2"}))
347
self.assertRaises(TypeError,
348
join_segment_parameters, "/,key1=val1", {"foo": 42})
273
350
def test_function_type(self):
274
351
if sys.platform == 'win32':
275
self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
276
self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
352
self.assertEqual(urlutils._win32_local_path_to_url,
353
urlutils.local_path_to_url)
354
self.assertEqual(urlutils._win32_local_path_from_url,
355
urlutils.local_path_from_url)
278
self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
279
self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
357
self.assertEqual(urlutils._posix_local_path_to_url,
358
urlutils.local_path_to_url)
359
self.assertEqual(urlutils._posix_local_path_from_url,
360
urlutils.local_path_from_url)
281
362
def test_posix_local_path_to_url(self):
282
363
to_url = urlutils._posix_local_path_to_url
283
364
self.assertEqual('file:///path/to/foo',
284
365
to_url('/path/to/foo'))
367
self.assertEqual('file:///path/to/foo%2Cbar',
368
to_url('/path/to/foo,bar'))
287
371
result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
288
372
except UnicodeError:
289
373
raise TestSkipped("local encoding cannot handle unicode")
291
375
self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
292
self.assertFalse(isinstance(result, unicode))
376
self.assertTrue(isinstance(result, str))
294
378
def test_posix_local_path_from_url(self):
295
379
from_url = urlutils._posix_local_path_from_url
296
380
self.assertEqual('/path/to/foo',
297
381
from_url('file:///path/to/foo'))
382
self.assertEqual('/path/to/foo',
383
from_url('file:///path/to/foo,branch=foo'))
298
384
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
299
385
from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
300
386
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
354
443
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
355
444
from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
356
445
self.assertEqual('/', from_url('file:///'))
446
self.assertEqual('C:/path/to/foo',
447
from_url('file:///C|/path/to/foo,branch=foo'))
358
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
449
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///C:')
450
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///c')
451
self.assertRaises(urlutils.InvalidURL, from_url, '/path/to/foo')
359
452
# Not a valid _win32 url, no drive letter
360
self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
453
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///path/to/foo')
362
455
def test_win32_unc_path_from_url(self):
363
456
from_url = urlutils._win32_local_path_from_url
364
457
self.assertEqual('//HOST/path', from_url('file://HOST/path'))
458
self.assertEqual('//HOST/path',
459
from_url('file://HOST/path,branch=foo'))
365
460
# despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
366
461
# we want to use only 2 slashes
367
462
# Firefox understand only 5 slashes in URL, but it's ugly
368
self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
369
self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
370
self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
463
self.assertRaises(urlutils.InvalidURL, from_url, 'file:////HOST/path')
464
self.assertRaises(urlutils.InvalidURL, from_url, 'file://///HOST/path')
465
self.assertRaises(urlutils.InvalidURL, from_url, 'file://////HOST/path')
371
466
# check for file://C:/ instead of file:///C:/
372
self.assertRaises(InvalidURL, from_url, 'file://C:/path')
467
self.assertRaises(urlutils.InvalidURL, from_url, 'file://C:/path')
374
469
def test_win32_extract_drive_letter(self):
375
470
extract = urlutils._win32_extract_drive_letter
376
471
self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
377
472
self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
378
self.assertRaises(InvalidURL, extract, 'file://', '/path')
473
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/path')
474
# Root drives without slash treated as invalid, see bug #841322
475
self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
476
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:')
477
# Invalid without drive separator or following forward slash
478
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C')
479
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:ool')
380
481
def test_split(self):
381
# Test bzrlib.urlutils.split()
482
# Test breezy.urlutils.split()
382
483
split = urlutils.split
383
484
if sys.platform == 'win32':
384
self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
485
self.assertRaises(urlutils.InvalidURL, split, 'file:///path/to/foo')
385
486
self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
386
487
self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
412
513
self.assertEqual(('path/..', 'foo'), split('path/../foo'))
413
514
self.assertEqual(('../path', 'foo'), split('../path/foo'))
516
def test_split_segment_parameters_raw(self):
517
split_segment_parameters_raw = urlutils.split_segment_parameters_raw
518
# Check relative references with absolute paths
519
self.assertEqual(("/some/path", []),
520
split_segment_parameters_raw("/some/path"))
521
self.assertEqual(("/some/path", ["tip"]),
522
split_segment_parameters_raw("/some/path,tip"))
523
self.assertEqual(("/some,dir/path", ["tip"]),
524
split_segment_parameters_raw("/some,dir/path,tip"))
525
self.assertEqual(("/somedir/path", ["heads%2Ftip"]),
526
split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
527
self.assertEqual(("/somedir/path", ["heads%2Ftip", "bar"]),
528
split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
529
# Check relative references with relative paths
530
self.assertEqual(("", ["key1=val1"]),
531
split_segment_parameters_raw(",key1=val1"))
532
self.assertEqual(("foo/", ["key1=val1"]),
533
split_segment_parameters_raw("foo/,key1=val1"))
534
self.assertEqual(("foo", ["key1=val1"]),
535
split_segment_parameters_raw("foo,key1=val1"))
536
self.assertEqual(("foo/base,la=bla/other/elements", []),
537
split_segment_parameters_raw("foo/base,la=bla/other/elements"))
538
self.assertEqual(("foo/base,la=bla/other/elements", ["a=b"]),
539
split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
540
# TODO: Check full URLs as well as relative references
542
def test_split_segment_parameters(self):
543
split_segment_parameters = urlutils.split_segment_parameters
544
# Check relative references with absolute paths
545
self.assertEqual(("/some/path", {}),
546
split_segment_parameters("/some/path"))
547
self.assertEqual(("/some/path", {"branch": "tip"}),
548
split_segment_parameters("/some/path,branch=tip"))
549
self.assertEqual(("/some,dir/path", {"branch": "tip"}),
550
split_segment_parameters("/some,dir/path,branch=tip"))
551
self.assertEqual(("/somedir/path", {"ref": "heads%2Ftip"}),
552
split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
553
self.assertEqual(("/somedir/path",
554
{"ref": "heads%2Ftip", "key1": "val1"}),
555
split_segment_parameters(
556
"/somedir/path,ref=heads%2Ftip,key1=val1"))
557
self.assertEqual(("/somedir/path", {"ref": "heads%2F=tip"}),
558
split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
559
# Check relative references with relative paths
560
self.assertEqual(("", {"key1": "val1"}),
561
split_segment_parameters(",key1=val1"))
562
self.assertEqual(("foo/", {"key1": "val1"}),
563
split_segment_parameters("foo/,key1=val1"))
564
self.assertEqual(("foo/base,key1=val1/other/elements", {}),
565
split_segment_parameters("foo/base,key1=val1/other/elements"))
566
self.assertEqual(("foo/base,key1=val1/other/elements",
567
{"key2": "val2"}), split_segment_parameters(
568
"foo/base,key1=val1/other/elements,key2=val2"))
569
# TODO: Check full URLs as well as relative references
415
571
def test_win32_strip_local_trailing_slash(self):
416
572
strip = urlutils._win32_strip_local_trailing_slash
417
573
self.assertEqual('file://', strip('file://'))
681
838
class TestParseURL(TestCase):
683
def test_parse_url(self):
684
self.assertEqual(urlutils.parse_url('http://example.com:80/one'),
685
('http', None, None, 'example.com', 80, '/one'))
686
self.assertEqual(urlutils.parse_url('http://[1:2:3::40]/one'),
687
('http', None, None, '1:2:3::40', None, '/one'))
688
self.assertEqual(urlutils.parse_url('http://[1:2:3::40]:80/one'),
689
('http', None, None, '1:2:3::40', 80, '/one'))
840
def test_parse_simple(self):
841
parsed = urlutils.parse_url('http://example.com:80/one')
842
self.assertEqual(('http', None, None, 'example.com', 80, '/one'),
846
parsed = urlutils.parse_url('http://[1:2:3::40]/one')
847
self.assertEqual(('http', None, None, '1:2:3::40', None, '/one'),
850
def test_ipv6_port(self):
851
parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
852
self.assertEqual(('http', None, None, '1:2:3::40', 80, '/one'),
856
class TestURL(TestCase):
858
def test_parse_simple(self):
859
parsed = urlutils.URL.from_string('http://example.com:80/one')
860
self.assertEqual('http', parsed.scheme)
861
self.assertIs(None, parsed.user)
862
self.assertIs(None, parsed.password)
863
self.assertEqual('example.com', parsed.host)
864
self.assertEqual(80, parsed.port)
865
self.assertEqual('/one', parsed.path)
868
parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
869
self.assertEqual('http', parsed.scheme)
870
self.assertIs(None, parsed.port)
871
self.assertIs(None, parsed.user)
872
self.assertIs(None, parsed.password)
873
self.assertEqual('1:2:3::40', parsed.host)
874
self.assertEqual('/one', parsed.path)
876
def test_ipv6_port(self):
877
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
878
self.assertEqual('http', parsed.scheme)
879
self.assertEqual('1:2:3::40', parsed.host)
880
self.assertIs(None, parsed.user)
881
self.assertIs(None, parsed.password)
882
self.assertEqual(80, parsed.port)
883
self.assertEqual('/one', parsed.path)
885
def test_quoted(self):
886
parsed = urlutils.URL.from_string(
887
'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
888
self.assertEqual(parsed.quoted_host, 'ex%41mple.com')
889
self.assertEqual(parsed.host, 'exAmple.com')
890
self.assertEqual(parsed.port, 2222)
891
self.assertEqual(parsed.quoted_user, 'ro%62ey')
892
self.assertEqual(parsed.user, 'robey')
893
self.assertEqual(parsed.quoted_password, 'h%40t')
894
self.assertEqual(parsed.password, 'h@t')
895
self.assertEqual(parsed.path, '/path')
898
parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
899
parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
900
self.assertEqual(parsed1, parsed2)
901
self.assertEqual(parsed1, parsed1)
902
parsed2.path = '/two'
903
self.assertNotEqual(parsed1, parsed2)
906
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
908
"<URL('http', None, None, '1:2:3::40', 80, '/one')>",
912
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
913
self.assertEqual('http://[1:2:3::40]:80/one', str(parsed))
915
def test__combine_paths(self):
916
combine = urlutils.URL._combine_paths
917
self.assertEqual('/home/sarah/project/foo',
918
combine('/home/sarah', 'project/foo'))
919
self.assertEqual('/etc',
920
combine('/home/sarah', '../../etc'))
921
self.assertEqual('/etc',
922
combine('/home/sarah', '../../../etc'))
923
self.assertEqual('/etc',
924
combine('/home/sarah', '/etc'))
926
def test_clone(self):
927
url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
928
url1 = url.clone("two")
929
self.assertEqual("/one/two", url1.path)
930
url2 = url.clone("/two")
931
self.assertEqual("/two", url2.path)
933
self.assertIsNot(url, url3)
934
self.assertEqual(url, url3)
936
def test_parse_empty_port(self):
937
parsed = urlutils.URL.from_string('http://example.com:/one')
938
self.assertEqual('http', parsed.scheme)
939
self.assertIs(None, parsed.user)
940
self.assertIs(None, parsed.password)
941
self.assertEqual('example.com', parsed.host)
942
self.assertIs(None, parsed.port)
943
self.assertEqual('/one', parsed.path)
946
class TestFileRelpath(TestCase):
948
# GZ 2011-11-18: A way to override all path handling functions to one
949
# platform or another for testing would be nice.
951
def _with_posix_paths(self):
952
self.overrideAttr(urlutils, "local_path_from_url",
953
urlutils._posix_local_path_from_url)
954
self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH", len("file:///"))
955
self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
956
self.overrideAttr(osutils, "abspath", osutils._posix_abspath)
957
self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
958
self.overrideAttr(osutils, "pathjoin", osutils.posixpath.join)
959
self.overrideAttr(osutils, "split", osutils.posixpath.split)
960
self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 1)
962
def _with_win32_paths(self):
963
self.overrideAttr(urlutils, "local_path_from_url",
964
urlutils._win32_local_path_from_url)
965
self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH",
966
urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
967
self.overrideAttr(osutils, "abspath", osutils._win32_abspath)
968
self.overrideAttr(osutils, "normpath", osutils._win32_normpath)
969
self.overrideAttr(osutils, "pathjoin", osutils._win32_pathjoin)
970
self.overrideAttr(osutils, "split", osutils.ntpath.split)
971
self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 3)
973
def test_same_url_posix(self):
974
self._with_posix_paths()
976
urlutils.file_relpath("file:///a", "file:///a"))
978
urlutils.file_relpath("file:///a", "file:///a/"))
980
urlutils.file_relpath("file:///a/", "file:///a"))
982
def test_same_url_win32(self):
983
self._with_win32_paths()
985
urlutils.file_relpath("file:///A:/", "file:///A:/"))
987
urlutils.file_relpath("file:///A|/", "file:///A:/"))
989
urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
991
urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
993
urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
995
def test_child_posix(self):
996
self._with_posix_paths()
997
self.assertEqual("b",
998
urlutils.file_relpath("file:///a", "file:///a/b"))
999
self.assertEqual("b",
1000
urlutils.file_relpath("file:///a/", "file:///a/b"))
1001
self.assertEqual("b/c",
1002
urlutils.file_relpath("file:///a", "file:///a/b/c"))
1004
def test_child_win32(self):
1005
self._with_win32_paths()
1006
self.assertEqual("b",
1007
urlutils.file_relpath("file:///A:/", "file:///A:/b"))
1008
self.assertEqual("b",
1009
urlutils.file_relpath("file:///A|/", "file:///A:/b"))
1010
self.assertEqual("c",
1011
urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
1012
self.assertEqual("c",
1013
urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
1014
self.assertEqual("c/d",
1015
urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
1017
def test_sibling_posix(self):
1018
self._with_posix_paths()
1019
self.assertRaises(PathNotChild,
1020
urlutils.file_relpath, "file:///a/b", "file:///a/c")
1021
self.assertRaises(PathNotChild,
1022
urlutils.file_relpath, "file:///a/b/", "file:///a/c")
1023
self.assertRaises(PathNotChild,
1024
urlutils.file_relpath, "file:///a/b/", "file:///a/c/")
1026
def test_sibling_win32(self):
1027
self._with_win32_paths()
1028
self.assertRaises(PathNotChild,
1029
urlutils.file_relpath, "file:///A:/b", "file:///A:/c")
1030
self.assertRaises(PathNotChild,
1031
urlutils.file_relpath, "file:///A:/b/", "file:///A:/c")
1032
self.assertRaises(PathNotChild,
1033
urlutils.file_relpath, "file:///A:/b/", "file:///A:/c/")
1035
def test_parent_posix(self):
1036
self._with_posix_paths()
1037
self.assertRaises(PathNotChild,
1038
urlutils.file_relpath, "file:///a/b", "file:///a")
1039
self.assertRaises(PathNotChild,
1040
urlutils.file_relpath, "file:///a/b", "file:///a/")
1042
def test_parent_win32(self):
1043
self._with_win32_paths()
1044
self.assertRaises(PathNotChild,
1045
urlutils.file_relpath, "file:///A:/b", "file:///A:/")
1046
self.assertRaises(PathNotChild,
1047
urlutils.file_relpath, "file:///A:/b/c", "file:///A:/b")
1050
class QuoteTests(TestCase):
1052
def test_quote(self):
1053
self.assertEqual('abc%20def', urlutils.quote('abc def'))
1054
self.assertEqual('abc%2Fdef', urlutils.quote('abc/def', safe=''))
1055
self.assertEqual('abc/def', urlutils.quote('abc/def', safe='/'))
1057
def test_quote_tildes(self):
1058
self.assertEqual('%7Efoo', urlutils.quote('~foo'))
1059
self.assertEqual('~foo', urlutils.quote('~foo', safe='/~'))
1061
def test_unquote(self):
1062
self.assertEqual('%', urlutils.unquote('%25'))
1064
self.assertEqual('\xe5', urlutils.unquote('%C3%A5'))
1066
self.assertEqual('\xc3\xa5', urlutils.unquote('%C3%A5'))
1067
self.assertEqual(u"\xe5", urlutils.unquote(u'\xe5'))
1069
def test_unquote_to_bytes(self):
1070
self.assertEqual(b'%', urlutils.unquote_to_bytes('%25'))
1071
self.assertEqual(b'\xc3\xa5', urlutils.unquote_to_bytes('%C3%A5'))