151
152
test_one('file:///usr/bin', ('file', '/usr/bin'))
152
153
test_one('file:///C:/Windows', ('file', '/C:/Windows'))
153
154
test_one('file:///C|/Windows', ('file', '/C|/Windows'))
154
test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
155
test_one(u'readonly+sftp://host/path/\xe5',
156
('readonly+sftp', u'host/path/\xe5'))
157
159
# Can't have slashes or colons in the scheme
158
160
test_one('/path/to/://foo', None)
159
test_one('path:path://foo', None)
161
test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
160
162
# Must have more than one character for scheme
161
163
test_one('C://foo', None)
162
164
test_one('ab://foo', ('ab', 'foo'))
164
166
def test_dirname(self):
165
# Test bzrlib.urlutils.dirname()
167
# Test breezy.urlutils.dirname()
166
168
dirname = urlutils.dirname
167
169
if sys.platform == 'win32':
168
self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
170
self.assertRaises(urlutils.InvalidURL, dirname,
171
'file:///path/to/foo')
169
172
self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
170
173
self.assertEqual('file:///C|/', dirname('file:///C|/'))
172
175
self.assertEqual('file:///', dirname('file:///foo'))
173
176
self.assertEqual('file:///', dirname('file:///'))
175
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
176
self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
178
self.assertEqual('http://host/path/to',
179
dirname('http://host/path/to/foo'))
180
self.assertEqual('http://host/path/to',
181
dirname('http://host/path/to/foo/'))
177
182
self.assertEqual('http://host/path/to/foo',
178
dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
183
dirname('http://host/path/to/foo/',
184
exclude_trailing_slash=False))
179
185
self.assertEqual('http://host/', dirname('http://host/path'))
180
186
self.assertEqual('http://host/', dirname('http://host/'))
181
187
self.assertEqual('http://host', dirname('http://host'))
182
188
self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
184
190
self.assertEqual('random+scheme://user:pass@ahost:port/',
185
dirname('random+scheme://user:pass@ahost:port/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/'))
191
dirname('random+scheme://user:pass@ahost:port/path'))
192
self.assertEqual('random+scheme://user:pass@ahost:port/',
193
dirname('random+scheme://user:pass@ahost:port/path/'))
194
self.assertEqual('random+scheme://user:pass@ahost:port/',
195
dirname('random+scheme://user:pass@ahost:port/'))
192
198
self.assertEqual('path/to', dirname('path/to/foo'))
193
199
self.assertEqual('path/to', dirname('path/to/foo/'))
194
200
self.assertEqual('path/to/foo',
195
dirname('path/to/foo/', exclude_trailing_slash=False))
201
dirname('path/to/foo/', exclude_trailing_slash=False))
196
202
self.assertEqual('path/..', dirname('path/../foo'))
197
203
self.assertEqual('../path', dirname('../path/foo'))
205
def test_is_url(self):
206
self.assertTrue(urlutils.is_url('http://foo/bar'))
207
self.assertTrue(urlutils.is_url('bzr+ssh://foo/bar'))
208
self.assertTrue(urlutils.is_url('lp:foo/bar'))
209
self.assertTrue(urlutils.is_url('file:///foo/bar'))
210
self.assertFalse(urlutils.is_url(''))
211
self.assertFalse(urlutils.is_url('foo'))
212
self.assertFalse(urlutils.is_url('foo/bar'))
213
self.assertFalse(urlutils.is_url('/foo'))
214
self.assertFalse(urlutils.is_url('/foo/bar'))
215
self.assertFalse(urlutils.is_url('C:/'))
216
self.assertFalse(urlutils.is_url('C:/foo'))
217
self.assertFalse(urlutils.is_url('C:/foo/bar'))
199
219
def test_join(self):
200
220
def test(expected, *args):
201
221
joined = urlutils.join(*args)
202
222
self.assertEqual(expected, joined)
204
224
# Test relative path joining
205
test('foo', 'foo') # relative fragment with nothing is preserved.
225
test('foo', 'foo') # relative fragment with nothing is preserved.
206
226
test('foo/bar', 'foo', 'bar')
207
227
test('http://foo/bar', 'http://foo', 'bar')
208
228
test('http://foo/bar', 'http://foo', '.', 'bar')
267
292
# Invalid joinings
268
293
# Cannot go above root
269
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
270
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
271
self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
294
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
296
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
298
self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
301
def test_join_segment_parameters_raw(self):
302
join_segment_parameters_raw = urlutils.join_segment_parameters_raw
303
self.assertEqual("/somedir/path",
304
join_segment_parameters_raw("/somedir/path"))
305
self.assertEqual("/somedir/path,rawdata",
306
join_segment_parameters_raw(
307
"/somedir/path", "rawdata"))
308
self.assertRaises(urlutils.InvalidURLJoin,
309
join_segment_parameters_raw, "/somedir/path",
310
"rawdata1,rawdata2,rawdata3")
311
self.assertEqual("/somedir/path,bla,bar",
312
join_segment_parameters_raw(
313
"/somedir/path", "bla", "bar"))
315
"/somedir,exist=some/path,bla,bar",
316
join_segment_parameters_raw("/somedir,exist=some/path",
318
self.assertRaises(TypeError, join_segment_parameters_raw,
321
def test_join_segment_parameters(self):
322
join_segment_parameters = urlutils.join_segment_parameters
323
self.assertEqual("/somedir/path",
324
join_segment_parameters("/somedir/path", {}))
326
"/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"})
332
urlutils.InvalidURLJoin,
333
join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
334
self.assertEqual("/somedir/path,key1=val1,key2=val2",
335
join_segment_parameters("/somedir/path", {
336
"key1": "val1", "key2": "val2"}))
337
self.assertEqual("/somedir/path,key1=val1,key2=val2",
338
join_segment_parameters("/somedir/path,key1=val1", {
340
self.assertEqual("/somedir/path,key1=val2",
341
join_segment_parameters("/somedir/path,key1=val1", {
343
self.assertEqual("/somedir,exist=some/path,key1=val1",
344
join_segment_parameters("/somedir,exist=some/path",
347
"/,key1=val1,key2=val2",
348
join_segment_parameters("/,key1=val1", {"key2": "val2"}))
349
self.assertRaises(TypeError,
350
join_segment_parameters, "/,key1=val1", {"foo": 42})
273
352
def test_function_type(self):
274
353
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)
354
self.assertEqual(urlutils._win32_local_path_to_url,
355
urlutils.local_path_to_url)
356
self.assertEqual(urlutils._win32_local_path_from_url,
357
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)
359
self.assertEqual(urlutils._posix_local_path_to_url,
360
urlutils.local_path_to_url)
361
self.assertEqual(urlutils._posix_local_path_from_url,
362
urlutils.local_path_from_url)
281
364
def test_posix_local_path_to_url(self):
282
365
to_url = urlutils._posix_local_path_to_url
283
366
self.assertEqual('file:///path/to/foo',
284
to_url('/path/to/foo'))
367
to_url('/path/to/foo'))
369
self.assertEqual('file:///path/to/foo%2Cbar',
370
to_url('/path/to/foo,bar'))
287
373
result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
318
407
# self.assertEqual('file:///C:/path/to/foo%20',
319
408
# to_url('C:/path/to/foo '))
320
409
self.assertEqual('file:///C:/path/to/f%20oo',
321
to_url('C:/path/to/f oo'))
410
to_url('C:/path/to/f oo'))
323
412
self.assertEqual('file:///', to_url('/'))
414
self.assertEqual('file:///C:/path/to/foo%2Cbar',
415
to_url('C:/path/to/foo,bar'))
326
417
result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
327
418
except UnicodeError:
328
419
raise TestSkipped("local encoding cannot handle unicode")
330
self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
331
self.assertFalse(isinstance(result, unicode))
422
'file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
423
self.assertIsInstance(result, str)
333
425
def test_win32_unc_path_to_url(self):
426
self.requireFeature(features.win32_feature)
334
427
to_url = urlutils._win32_local_path_to_url
335
428
self.assertEqual('file://HOST/path',
336
to_url(r'\\HOST\path'))
429
to_url(r'\\HOST\path'))
337
430
self.assertEqual('file://HOST/path',
338
to_url('//HOST/path'))
431
to_url('//HOST/path'))
341
434
result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
342
435
except UnicodeError:
343
436
raise TestSkipped("local encoding cannot handle unicode")
345
self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
346
self.assertFalse(isinstance(result, unicode))
439
'file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
440
self.assertFalse(isinstance(result, str))
348
442
def test_win32_local_path_from_url(self):
349
443
from_url = urlutils._win32_local_path_from_url
350
444
self.assertEqual('C:/path/to/foo',
351
from_url('file:///C|/path/to/foo'))
352
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
445
from_url('file:///C|/path/to/foo'))
447
u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
353
448
from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
354
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
450
u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
355
451
from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
356
452
self.assertEqual('/', from_url('file:///'))
453
self.assertEqual('C:/path/to/foo',
454
from_url('file:///C|/path/to/foo,branch=foo'))
358
self.assertRaises(InvalidURL, from_url, '/path/to/foo')
456
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///C:')
457
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///c')
458
self.assertRaises(urlutils.InvalidURL, from_url, '/path/to/foo')
359
459
# Not a valid _win32 url, no drive letter
360
self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
460
self.assertRaises(urlutils.InvalidURL, from_url, 'file:///path/to/foo')
362
462
def test_win32_unc_path_from_url(self):
363
463
from_url = urlutils._win32_local_path_from_url
364
464
self.assertEqual('//HOST/path', from_url('file://HOST/path'))
465
self.assertEqual('//HOST/path',
466
from_url('file://HOST/path,branch=foo'))
365
467
# despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
366
468
# we want to use only 2 slashes
367
469
# 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')
470
self.assertRaises(urlutils.InvalidURL, from_url, 'file:////HOST/path')
471
self.assertRaises(urlutils.InvalidURL, from_url, 'file://///HOST/path')
472
self.assertRaises(urlutils.InvalidURL, from_url,
473
'file://////HOST/path')
371
474
# check for file://C:/ instead of file:///C:/
372
self.assertRaises(InvalidURL, from_url, 'file://C:/path')
475
self.assertRaises(urlutils.InvalidURL, from_url, 'file://C:/path')
374
477
def test_win32_extract_drive_letter(self):
375
478
extract = urlutils._win32_extract_drive_letter
376
479
self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
377
self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
378
self.assertRaises(InvalidURL, extract, 'file://', '/path')
480
self.assertEqual(('file:///d|', '/path'),
481
extract('file://', '/d|/path'))
482
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/path')
483
# Root drives without slash treated as invalid, see bug #841322
484
self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
485
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:')
486
# Invalid without drive separator or following forward slash
487
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C')
488
self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:ool')
380
490
def test_split(self):
381
# Test bzrlib.urlutils.split()
491
# Test breezy.urlutils.split()
382
492
split = urlutils.split
383
493
if sys.platform == 'win32':
384
self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
494
self.assertRaises(urlutils.InvalidURL, split,
495
'file:///path/to/foo')
385
496
self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
386
497
self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
388
499
self.assertEqual(('file:///', 'foo'), split('file:///foo'))
389
500
self.assertEqual(('file:///', ''), split('file:///'))
391
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
392
self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
393
self.assertEqual(('http://host/path/to/foo', ''),
502
self.assertEqual(('http://host/path/to', 'foo'),
503
split('http://host/path/to/foo'))
504
self.assertEqual(('http://host/path/to', 'foo'),
505
split('http://host/path/to/foo/'))
507
('http://host/path/to/foo', ''),
394
508
split('http://host/path/to/foo/', exclude_trailing_slash=False))
395
509
self.assertEqual(('http://host/', 'path'), split('http://host/path'))
396
510
self.assertEqual(('http://host/', ''), split('http://host/'))
397
511
self.assertEqual(('http://host', ''), split('http://host'))
398
self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
512
self.assertEqual(('http:///nohost', 'path'),
513
split('http:///nohost/path'))
400
515
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
401
split('random+scheme://user:pass@ahost:port/path'))
516
split('random+scheme://user:pass@ahost:port/path'))
402
517
self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
403
split('random+scheme://user:pass@ahost:port/path/'))
518
split('random+scheme://user:pass@ahost:port/path/'))
404
519
self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
405
split('random+scheme://user:pass@ahost:port/'))
520
split('random+scheme://user:pass@ahost:port/'))
408
523
self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
409
524
self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
410
525
self.assertEqual(('path/to/foo', ''),
411
split('path/to/foo/', exclude_trailing_slash=False))
526
split('path/to/foo/', exclude_trailing_slash=False))
412
527
self.assertEqual(('path/..', 'foo'), split('path/../foo'))
413
528
self.assertEqual(('../path', 'foo'), split('../path/foo'))
530
def test_strip_segment_parameters(self):
531
strip_segment_parameters = urlutils.strip_segment_parameters
532
# Check relative references with absolute paths
533
self.assertEqual("/some/path",
534
strip_segment_parameters("/some/path"))
535
self.assertEqual("/some/path",
536
strip_segment_parameters("/some/path,tip"))
537
self.assertEqual("/some,dir/path",
538
strip_segment_parameters("/some,dir/path,tip"))
541
strip_segment_parameters("/somedir/path,heads%2Ftip"))
544
strip_segment_parameters("/somedir/path,heads%2Ftip,bar"))
545
# Check relative references with relative paths
546
self.assertEqual("", strip_segment_parameters(",key1=val1"))
547
self.assertEqual("foo/", strip_segment_parameters("foo/,key1=val1"))
548
self.assertEqual("foo", strip_segment_parameters("foo,key1=val1"))
550
"foo/base,la=bla/other/elements",
551
strip_segment_parameters("foo/base,la=bla/other/elements"))
553
"foo/base,la=bla/other/elements",
554
strip_segment_parameters("foo/base,la=bla/other/elements,a=b"))
555
# TODO: Check full URLs as well as relative references
557
def test_split_segment_parameters_raw(self):
558
split_segment_parameters_raw = urlutils.split_segment_parameters_raw
559
# Check relative references with absolute paths
560
self.assertEqual(("/some/path", []),
561
split_segment_parameters_raw("/some/path"))
562
self.assertEqual(("/some/path", ["tip"]),
563
split_segment_parameters_raw("/some/path,tip"))
564
self.assertEqual(("/some,dir/path", ["tip"]),
565
split_segment_parameters_raw("/some,dir/path,tip"))
567
("/somedir/path", ["heads%2Ftip"]),
568
split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
570
("/somedir/path", ["heads%2Ftip", "bar"]),
571
split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
572
# Check relative references with relative paths
573
self.assertEqual(("", ["key1=val1"]),
574
split_segment_parameters_raw(",key1=val1"))
575
self.assertEqual(("foo/", ["key1=val1"]),
576
split_segment_parameters_raw("foo/,key1=val1"))
577
self.assertEqual(("foo", ["key1=val1"]),
578
split_segment_parameters_raw("foo,key1=val1"))
580
("foo/base,la=bla/other/elements", []),
581
split_segment_parameters_raw("foo/base,la=bla/other/elements"))
583
("foo/base,la=bla/other/elements", ["a=b"]),
584
split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
585
# TODO: Check full URLs as well as relative references
587
def test_split_segment_parameters(self):
588
split_segment_parameters = urlutils.split_segment_parameters
589
# Check relative references with absolute paths
590
self.assertEqual(("/some/path", {}),
591
split_segment_parameters("/some/path"))
592
self.assertEqual(("/some/path", {"branch": "tip"}),
593
split_segment_parameters("/some/path,branch=tip"))
594
self.assertEqual(("/some,dir/path", {"branch": "tip"}),
595
split_segment_parameters("/some,dir/path,branch=tip"))
597
("/somedir/path", {"ref": "heads%2Ftip"}),
598
split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
599
self.assertEqual(("/somedir/path",
600
{"ref": "heads%2Ftip", "key1": "val1"}),
601
split_segment_parameters(
602
"/somedir/path,ref=heads%2Ftip,key1=val1"))
604
("/somedir/path", {"ref": "heads%2F=tip"}),
605
split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
606
# Check relative references with relative paths
607
self.assertEqual(("", {"key1": "val1"}),
608
split_segment_parameters(",key1=val1"))
609
self.assertEqual(("foo/", {"key1": "val1"}),
610
split_segment_parameters("foo/,key1=val1"))
612
("foo/base,key1=val1/other/elements", {}),
613
split_segment_parameters("foo/base,key1=val1/other/elements"))
614
self.assertEqual(("foo/base,key1=val1/other/elements",
615
{"key2": "val2"}), split_segment_parameters(
616
"foo/base,key1=val1/other/elements,key2=val2"))
618
urlutils.InvalidURL, split_segment_parameters,
620
# TODO: Check full URLs as well as relative references
415
622
def test_win32_strip_local_trailing_slash(self):
416
623
strip = urlutils._win32_strip_local_trailing_slash
417
624
self.assertEqual('file://', strip('file://'))
524
731
test('a', 'http://host/', 'http://host/a')
525
732
test('http://entirely/different', 'sftp://host/branch',
526
'http://entirely/different')
733
'http://entirely/different')
527
734
test('../person/feature', 'http://host/branch/mainline',
528
'http://host/branch/person/feature')
735
'http://host/branch/person/feature')
529
736
test('..', 'http://host/branch', 'http://host/')
530
test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
737
test('http://host2/branch', 'http://host1/branch',
738
'http://host2/branch')
531
739
test('.', 'http://host1/branch', 'http://host1/branch')
532
740
test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
533
'file:///home/jelmer/branch/2b')
741
'file:///home/jelmer/branch/2b')
534
742
test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
535
'sftp://host/home/jelmer/branch/2b')
743
'sftp://host/home/jelmer/branch/2b')
536
744
test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
537
'http://host/home/jelmer/branch/feature/%2b')
745
'http://host/home/jelmer/branch/feature/%2b')
538
746
test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
539
'http://host/home/jelmer/branch/feature/2b')
747
'http://host/home/jelmer/branch/feature/2b')
540
748
# relative_url should preserve a trailing slash
541
749
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
542
'http://host/home/jelmer/branch/feature/2b/')
750
'http://host/home/jelmer/branch/feature/2b/')
543
751
test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
544
'http://host/home/jelmer/branch/feature/2b/')
752
'http://host/home/jelmer/branch/feature/2b/')
546
754
# TODO: treat http://host as http://host/
547
755
# relative_url is typically called from a branch.base or
548
756
# transport.base which always ends with a /
549
#test('a', 'http://host', 'http://host/a')
757
# test('a', 'http://host', 'http://host/a')
550
758
test('http://host/a', 'http://host', 'http://host/a')
551
#test('.', 'http://host', 'http://host/')
759
# test('.', 'http://host', 'http://host/')
552
760
test('http://host/', 'http://host', 'http://host/')
553
#test('.', 'http://host/', 'http://host')
761
# test('.', 'http://host/', 'http://host')
554
762
test('http://host', 'http://host/', 'http://host')
556
764
# On Windows file:///C:/path/to and file:///D:/other/path
637
842
self.assertEqual('/foo', result)
639
844
def test_different_ports(self):
640
e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
845
e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
641
846
'foo', 'http://bar:80', 'http://bar:81')
642
847
self.assertEqual(str(e), "URLs differ by more than path:"
643
848
" 'http://bar:80' and 'http://bar:81'")
645
850
def test_different_hosts(self):
646
e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
851
e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
647
852
'foo', 'http://bar', 'http://baz')
648
853
self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
649
854
" and 'http://baz'")
651
856
def test_different_protocol(self):
652
e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
857
e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
653
858
'foo', 'http://bar', 'ftp://bar')
654
859
self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
655
860
" and 'ftp://bar'")
657
862
def test_rebase_success(self):
658
863
self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
660
self.assertEqual('qux/bar', urlutils.rebase_url('bar',
661
'http://baz/qux', 'http://baz/'))
662
self.assertEqual('.', urlutils.rebase_url('foo',
663
'http://bar/', 'http://bar/foo/'))
664
self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
665
'http://baz/qux/foo', 'http://baz/'))
867
urlutils.rebase_url('bar', 'http://baz/qux', 'http://baz/'))
869
'.', urlutils.rebase_url('foo', 'http://bar/', 'http://bar/foo/'))
872
urlutils.rebase_url('../bar', 'http://baz/qux/foo', 'http://baz/'))
667
874
def test_determine_relative_path(self):
668
875
self.assertEqual('../../baz/bar',
669
876
urlutils.determine_relative_path(
670
'/qux/quxx', '/baz/bar'))
877
'/qux/quxx', '/baz/bar'))
671
878
self.assertEqual('..',
672
879
urlutils.determine_relative_path(
674
881
self.assertEqual('baz',
675
882
urlutils.determine_relative_path(
677
884
self.assertEqual('.', urlutils.determine_relative_path(
681
888
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'))
890
def test_parse_simple(self):
891
parsed = urlutils.parse_url('http://example.com:80/one')
892
self.assertEqual(('http', None, None, 'example.com', 80, '/one'),
896
parsed = urlutils.parse_url('http://[1:2:3::40]/one')
897
self.assertEqual(('http', None, None, '1:2:3::40', None, '/one'),
900
def test_ipv6_port(self):
901
parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
902
self.assertEqual(('http', None, None, '1:2:3::40', 80, '/one'),
906
class TestURL(TestCase):
908
def test_parse_simple(self):
909
parsed = urlutils.URL.from_string('http://example.com:80/one')
910
self.assertEqual('http', parsed.scheme)
911
self.assertIs(None, parsed.user)
912
self.assertIs(None, parsed.password)
913
self.assertEqual('example.com', parsed.host)
914
self.assertEqual(80, parsed.port)
915
self.assertEqual('/one', parsed.path)
918
parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
919
self.assertEqual('http', parsed.scheme)
920
self.assertIs(None, parsed.port)
921
self.assertIs(None, parsed.user)
922
self.assertIs(None, parsed.password)
923
self.assertEqual('1:2:3::40', parsed.host)
924
self.assertEqual('/one', parsed.path)
926
def test_ipv6_port(self):
927
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
928
self.assertEqual('http', parsed.scheme)
929
self.assertEqual('1:2:3::40', parsed.host)
930
self.assertIs(None, parsed.user)
931
self.assertIs(None, parsed.password)
932
self.assertEqual(80, parsed.port)
933
self.assertEqual('/one', parsed.path)
935
def test_quoted(self):
936
parsed = urlutils.URL.from_string(
937
'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
938
self.assertEqual(parsed.quoted_host, 'ex%41mple.com')
939
self.assertEqual(parsed.host, 'exAmple.com')
940
self.assertEqual(parsed.port, 2222)
941
self.assertEqual(parsed.quoted_user, 'ro%62ey')
942
self.assertEqual(parsed.user, 'robey')
943
self.assertEqual(parsed.quoted_password, 'h%40t')
944
self.assertEqual(parsed.password, 'h@t')
945
self.assertEqual(parsed.path, '/path')
948
parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
949
parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
950
self.assertEqual(parsed1, parsed2)
951
self.assertEqual(parsed1, parsed1)
952
parsed2.path = '/two'
953
self.assertNotEqual(parsed1, parsed2)
956
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
958
"<URL('http', None, None, '1:2:3::40', 80, '/one')>",
962
parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
963
self.assertEqual('http://[1:2:3::40]:80/one', str(parsed))
965
def test__combine_paths(self):
966
combine = urlutils.URL._combine_paths
967
self.assertEqual('/home/sarah/project/foo',
968
combine('/home/sarah', 'project/foo'))
969
self.assertEqual('/etc',
970
combine('/home/sarah', '../../etc'))
971
self.assertEqual('/etc',
972
combine('/home/sarah', '../../../etc'))
973
self.assertEqual('/etc',
974
combine('/home/sarah', '/etc'))
976
def test_clone(self):
977
url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
978
url1 = url.clone("two")
979
self.assertEqual("/one/two", url1.path)
980
url2 = url.clone("/two")
981
self.assertEqual("/two", url2.path)
983
self.assertIsNot(url, url3)
984
self.assertEqual(url, url3)
986
def test_parse_empty_port(self):
987
parsed = urlutils.URL.from_string('http://example.com:/one')
988
self.assertEqual('http', parsed.scheme)
989
self.assertIs(None, parsed.user)
990
self.assertIs(None, parsed.password)
991
self.assertEqual('example.com', parsed.host)
992
self.assertIs(None, parsed.port)
993
self.assertEqual('/one', parsed.path)
996
class TestFileRelpath(TestCase):
998
# GZ 2011-11-18: A way to override all path handling functions to one
999
# platform or another for testing would be nice.
1001
def _with_posix_paths(self):
1002
self.overrideAttr(urlutils, "local_path_from_url",
1003
urlutils._posix_local_path_from_url)
1004
self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH", len("file:///"))
1005
self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
1006
self.overrideAttr(osutils, "abspath", osutils._posix_abspath)
1007
self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
1008
self.overrideAttr(osutils, "pathjoin", osutils.posixpath.join)
1009
self.overrideAttr(osutils, "split", osutils.posixpath.split)
1010
self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 1)
1012
def _with_win32_paths(self):
1013
self.overrideAttr(urlutils, "local_path_from_url",
1014
urlutils._win32_local_path_from_url)
1015
self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH",
1016
urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
1017
self.overrideAttr(osutils, "abspath", osutils._win32_abspath)
1018
self.overrideAttr(osutils, "normpath", osutils._win32_normpath)
1019
self.overrideAttr(osutils, "pathjoin", osutils._win32_pathjoin)
1020
self.overrideAttr(osutils, "split", osutils.ntpath.split)
1021
self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 3)
1023
def test_same_url_posix(self):
1024
self._with_posix_paths()
1025
self.assertEqual("",
1026
urlutils.file_relpath("file:///a", "file:///a"))
1027
self.assertEqual("",
1028
urlutils.file_relpath("file:///a", "file:///a/"))
1029
self.assertEqual("",
1030
urlutils.file_relpath("file:///a/", "file:///a"))
1032
def test_same_url_win32(self):
1033
self._with_win32_paths()
1034
self.assertEqual("",
1035
urlutils.file_relpath("file:///A:/", "file:///A:/"))
1036
self.assertEqual("",
1037
urlutils.file_relpath("file:///A|/", "file:///A:/"))
1039
"", urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
1041
"", urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
1043
"", urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
1045
def test_child_posix(self):
1046
self._with_posix_paths()
1048
"b", urlutils.file_relpath("file:///a", "file:///a/b"))
1050
"b", urlutils.file_relpath("file:///a/", "file:///a/b"))
1052
"b/c", urlutils.file_relpath("file:///a", "file:///a/b/c"))
1054
def test_child_win32(self):
1055
self._with_win32_paths()
1057
"b", urlutils.file_relpath("file:///A:/", "file:///A:/b"))
1059
"b", urlutils.file_relpath("file:///A|/", "file:///A:/b"))
1061
"c", urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
1063
"c", urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
1065
"c/d", urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
1067
def test_sibling_posix(self):
1068
self._with_posix_paths()
1071
urlutils.file_relpath, "file:///a/b", "file:///a/c")
1074
urlutils.file_relpath, "file:///a/b/", "file:///a/c")
1077
urlutils.file_relpath, "file:///a/b/", "file:///a/c/")
1079
def test_sibling_win32(self):
1080
self._with_win32_paths()
1083
urlutils.file_relpath, "file:///A:/b", "file:///A:/c")
1086
urlutils.file_relpath, "file:///A:/b/", "file:///A:/c")
1089
urlutils.file_relpath, "file:///A:/b/", "file:///A:/c/")
1091
def test_parent_posix(self):
1092
self._with_posix_paths()
1093
self.assertRaises(PathNotChild,
1094
urlutils.file_relpath, "file:///a/b", "file:///a")
1095
self.assertRaises(PathNotChild,
1096
urlutils.file_relpath, "file:///a/b", "file:///a/")
1098
def test_parent_win32(self):
1099
self._with_win32_paths()
1102
urlutils.file_relpath, "file:///A:/b", "file:///A:/")
1105
urlutils.file_relpath, "file:///A:/b/c", "file:///A:/b")
1108
class QuoteTests(TestCase):
1110
def test_quote(self):
1111
self.assertEqual('abc%20def', urlutils.quote('abc def'))
1112
self.assertEqual('abc%2Fdef', urlutils.quote('abc/def', safe=''))
1113
self.assertEqual('abc/def', urlutils.quote('abc/def', safe='/'))
1115
def test_quote_tildes(self):
1116
# Whether ~ is quoted by default depends on the python version
1117
if sys.version_info[:2] >= (3, 7):
1118
# https://docs.python.org/3/whatsnew/3.7.html#urllib-parse
1119
self.assertEqual('~foo', urlutils.quote('~foo'))
1121
self.assertEqual('%7Efoo', urlutils.quote('~foo'))
1122
self.assertEqual('~foo', urlutils.quote('~foo', safe='/~'))
1124
def test_unquote(self):
1125
self.assertEqual('%', urlutils.unquote('%25'))
1126
self.assertEqual('\xe5', urlutils.unquote('%C3%A5'))
1127
self.assertEqual(u"\xe5", urlutils.unquote(u'\xe5'))
1129
def test_unquote_to_bytes(self):
1130
self.assertEqual(b'%', urlutils.unquote_to_bytes('%25'))
1131
self.assertEqual(b'\xc3\xa5', urlutils.unquote_to_bytes('%C3%A5'))