~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Patch Queue Manager
  • Date: 2016-04-21 04:10:52 UTC
  • mfrom: (6616.1.1 fix-en-user-guide)
  • Revision ID: pqm@pqm.ubuntu.com-20160421041052-clcye7ns1qcl2n7w
(richard-wilbur) Ensure build of English use guide always uses English text
 even when user's locale specifies a different language. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2006-2012, 2015, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the urlutils wrapper."""
18
18
 
19
19
import os
20
 
import re
21
20
import sys
22
21
 
23
22
from bzrlib import osutils, urlutils, win32utils
24
 
import bzrlib
25
 
from bzrlib.errors import InvalidURL, InvalidURLJoin
26
 
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
 
23
from bzrlib.errors import (
 
24
    InvalidURL,
 
25
    InvalidURLJoin,
 
26
    InvalidRebaseURLs,
 
27
    PathNotChild,
 
28
    )
 
29
from bzrlib.tests import features, TestCaseInTempDir, TestCase, TestSkipped
27
30
 
28
31
 
29
32
class TestUrlToPath(TestCase):
30
 
    
 
33
 
31
34
    def test_basename(self):
32
35
        # bzrlib.urlutils.basename
33
36
        # Test bzrlib.urlutils.split()
82
85
 
83
86
        # Local paths are assumed to *not* be escaped at all
84
87
        try:
85
 
            u'uni/\xb5'.encode(bzrlib.user_encoding)
 
88
            u'uni/\xb5'.encode(osutils.get_user_encoding())
86
89
        except UnicodeError:
87
 
            # locale cannot handle unicode 
 
90
            # locale cannot handle unicode
88
91
            pass
89
92
        else:
90
93
            norm_file('uni/%C2%B5', u'uni/\xb5')
158
161
        # Weird stuff
159
162
        # Can't have slashes or colons in the scheme
160
163
        test_one('/path/to/://foo', None)
161
 
        test_one('path:path://foo', None)
 
164
        test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
162
165
        # Must have more than one character for scheme
163
166
        test_one('C://foo', None)
164
167
        test_one('ab://foo', ('ab', 'foo'))
197
200
            dirname('path/to/foo/', exclude_trailing_slash=False))
198
201
        self.assertEqual('path/..', dirname('path/../foo'))
199
202
        self.assertEqual('../path', dirname('../path/foo'))
 
203
    
 
204
    def test_is_url(self):
 
205
        self.assertTrue(urlutils.is_url('http://foo/bar'))
 
206
        self.assertTrue(urlutils.is_url('bzr+ssh://foo/bar'))
 
207
        self.assertTrue(urlutils.is_url('lp:foo/bar'))
 
208
        self.assertTrue(urlutils.is_url('file:///foo/bar'))
 
209
        self.assertFalse(urlutils.is_url(''))
 
210
        self.assertFalse(urlutils.is_url('foo'))
 
211
        self.assertFalse(urlutils.is_url('foo/bar'))
 
212
        self.assertFalse(urlutils.is_url('/foo'))
 
213
        self.assertFalse(urlutils.is_url('/foo/bar'))
 
214
        self.assertFalse(urlutils.is_url('C:/'))
 
215
        self.assertFalse(urlutils.is_url('C:/foo'))
 
216
        self.assertFalse(urlutils.is_url('C:/foo/bar'))
200
217
 
201
218
    def test_join(self):
202
219
        def test(expected, *args):
212
229
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
213
230
        test('http://foo/baz', 'http://foo', 'bar/../baz')
214
231
        test('http://foo/baz', 'http://foo/bar/', '../baz')
 
232
        test('lp:foo/bar', 'lp:foo', 'bar')
 
233
        test('lp:foo/bar/baz', 'lp:foo', 'bar/baz')
215
234
 
216
235
        # Absolute paths
217
236
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
221
240
        test('http://bar/', 'http://foo', 'http://bar/')
222
241
        test('http://bar/a', 'http://foo', 'http://bar/a')
223
242
        test('http://bar/a/', 'http://foo', 'http://bar/a/')
 
243
        test('lp:bar', 'http://foo', 'lp:bar')
 
244
        test('lp:bar', 'lp:foo', 'lp:bar')
 
245
        test('file:///stuff', 'lp:foo', 'file:///stuff')
224
246
 
225
247
        # From a base path
226
248
        test('file:///foo', 'file:///', 'foo')
227
249
        test('file:///bar/foo', 'file:///bar/', 'foo')
228
250
        test('http://host/foo', 'http://host/', 'foo')
229
251
        test('http://host/', 'http://host', '')
230
 
        
 
252
 
231
253
        # Invalid joinings
232
254
        # Cannot go above root
233
255
        # Implicitly at root:
265
287
 
266
288
        # Test joining to a path with a trailing slash
267
289
        test('foo/bar', 'foo/', 'bar')
268
 
        
 
290
 
269
291
        # Invalid joinings
270
292
        # Cannot go above root
271
293
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
272
294
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
273
295
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
274
296
 
 
297
    def test_join_segment_parameters_raw(self):
 
298
        join_segment_parameters_raw = urlutils.join_segment_parameters_raw
 
299
        self.assertEqual("/somedir/path", 
 
300
            join_segment_parameters_raw("/somedir/path"))
 
301
        self.assertEqual("/somedir/path,rawdata", 
 
302
            join_segment_parameters_raw("/somedir/path", "rawdata"))
 
303
        self.assertRaises(InvalidURLJoin,
 
304
            join_segment_parameters_raw, "/somedir/path",
 
305
                "rawdata1,rawdata2,rawdata3")
 
306
        self.assertEqual("/somedir/path,bla,bar",
 
307
            join_segment_parameters_raw("/somedir/path", "bla", "bar"))
 
308
        self.assertEqual("/somedir,exist=some/path,bla,bar",
 
309
            join_segment_parameters_raw("/somedir,exist=some/path",
 
310
                "bla", "bar"))
 
311
        self.assertRaises(TypeError, join_segment_parameters_raw, 
 
312
            "/somepath", 42)
 
313
 
 
314
    def test_join_segment_parameters(self):
 
315
        join_segment_parameters = urlutils.join_segment_parameters
 
316
        self.assertEqual("/somedir/path", 
 
317
            join_segment_parameters("/somedir/path", {}))
 
318
        self.assertEqual("/somedir/path,key1=val1", 
 
319
            join_segment_parameters("/somedir/path", {"key1": "val1"}))
 
320
        self.assertRaises(InvalidURLJoin,
 
321
            join_segment_parameters, "/somedir/path",
 
322
            {"branch": "brr,brr,brr"})
 
323
        self.assertRaises(InvalidURLJoin,
 
324
            join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
 
325
        self.assertEqual("/somedir/path,key1=val1,key2=val2",
 
326
            join_segment_parameters("/somedir/path", {
 
327
                "key1": "val1", "key2": "val2"}))
 
328
        self.assertEqual("/somedir/path,key1=val1,key2=val2",
 
329
            join_segment_parameters("/somedir/path,key1=val1", {
 
330
                "key2": "val2"}))
 
331
        self.assertEqual("/somedir/path,key1=val2",
 
332
            join_segment_parameters("/somedir/path,key1=val1", {
 
333
                "key1": "val2"}))
 
334
        self.assertEqual("/somedir,exist=some/path,key1=val1",
 
335
            join_segment_parameters("/somedir,exist=some/path",
 
336
                {"key1": "val1"}))
 
337
        self.assertEqual("/,key1=val1,key2=val2",
 
338
            join_segment_parameters("/,key1=val1", {"key2": "val2"}))
 
339
        self.assertRaises(TypeError,
 
340
            join_segment_parameters, "/,key1=val1", {"foo": 42})
 
341
 
275
342
    def test_function_type(self):
276
343
        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)
 
344
            self.assertEqual(urlutils._win32_local_path_to_url,
 
345
                urlutils.local_path_to_url)
 
346
            self.assertEqual(urlutils._win32_local_path_from_url,
 
347
                urlutils.local_path_from_url)
279
348
        else:
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)
 
349
            self.assertEqual(urlutils._posix_local_path_to_url,
 
350
                urlutils.local_path_to_url)
 
351
            self.assertEqual(urlutils._posix_local_path_from_url,
 
352
                urlutils.local_path_from_url)
282
353
 
283
354
    def test_posix_local_path_to_url(self):
284
355
        to_url = urlutils._posix_local_path_to_url
285
356
        self.assertEqual('file:///path/to/foo',
286
357
            to_url('/path/to/foo'))
287
358
 
 
359
        self.assertEqual('file:///path/to/foo%2Cbar',
 
360
            to_url('/path/to/foo,bar'))
 
361
 
288
362
        try:
289
363
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
290
364
        except UnicodeError:
291
365
            raise TestSkipped("local encoding cannot handle unicode")
292
366
 
293
367
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
368
        self.assertFalse(isinstance(result, unicode))
294
369
 
295
370
    def test_posix_local_path_from_url(self):
296
371
        from_url = urlutils._posix_local_path_from_url
297
372
        self.assertEqual('/path/to/foo',
298
373
            from_url('file:///path/to/foo'))
 
374
        self.assertEqual('/path/to/foo',
 
375
            from_url('file:///path/to/foo,branch=foo'))
299
376
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
300
377
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
301
378
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
302
379
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
380
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
 
381
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
303
382
 
304
383
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
 
384
        self.assertRaises(
 
385
            InvalidURL, from_url,
 
386
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
305
387
 
306
388
    def test_win32_local_path_to_url(self):
307
389
        to_url = urlutils._win32_local_path_to_url
316
398
        self.assertEqual('file:///C:/path/to/f%20oo',
317
399
            to_url('C:/path/to/f oo'))
318
400
 
 
401
        self.assertEqual('file:///', to_url('/'))
 
402
 
 
403
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
 
404
            to_url('C:/path/to/foo,bar'))
319
405
        try:
320
406
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
321
407
        except UnicodeError:
322
408
            raise TestSkipped("local encoding cannot handle unicode")
323
409
 
324
410
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
411
        self.assertFalse(isinstance(result, unicode))
325
412
 
326
413
    def test_win32_unc_path_to_url(self):
 
414
        self.requireFeature(features.win32_feature)
327
415
        to_url = urlutils._win32_local_path_to_url
328
416
        self.assertEqual('file://HOST/path',
329
417
            to_url(r'\\HOST\path'))
336
424
            raise TestSkipped("local encoding cannot handle unicode")
337
425
 
338
426
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
339
 
 
 
427
        self.assertFalse(isinstance(result, unicode))
340
428
 
341
429
    def test_win32_local_path_from_url(self):
342
430
        from_url = urlutils._win32_local_path_from_url
346
434
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
347
435
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
348
436
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
437
        self.assertEqual('/', from_url('file:///'))
 
438
        self.assertEqual('C:/path/to/foo',
 
439
            from_url('file:///C|/path/to/foo,branch=foo'))
349
440
 
 
441
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
 
442
        self.assertRaises(InvalidURL, from_url, 'file:///c')
350
443
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
351
444
        # Not a valid _win32 url, no drive letter
352
445
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
354
447
    def test_win32_unc_path_from_url(self):
355
448
        from_url = urlutils._win32_local_path_from_url
356
449
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
 
450
        self.assertEqual('//HOST/path',
 
451
            from_url('file://HOST/path,branch=foo'))
357
452
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
358
453
        # we want to use only 2 slashes
359
454
        # Firefox understand only 5 slashes in URL, but it's ugly
368
463
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
369
464
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
370
465
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
 
466
        # Root drives without slash treated as invalid, see bug #841322
 
467
        self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
 
468
        self.assertRaises(InvalidURL, extract, 'file://', '/C:')
 
469
        # Invalid without drive separator or following forward slash
 
470
        self.assertRaises(InvalidURL, extract, 'file://', '/C')
 
471
        self.assertRaises(InvalidURL, extract, 'file://', '/C:ool')
371
472
 
372
473
    def test_split(self):
373
474
        # Test bzrlib.urlutils.split()
404
505
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
405
506
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
406
507
 
 
508
    def test_split_segment_parameters_raw(self):
 
509
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
 
510
        # Check relative references with absolute paths
 
511
        self.assertEqual(("/some/path", []),
 
512
            split_segment_parameters_raw("/some/path"))
 
513
        self.assertEqual(("/some/path", ["tip"]),
 
514
            split_segment_parameters_raw("/some/path,tip"))
 
515
        self.assertEqual(("/some,dir/path", ["tip"]),
 
516
            split_segment_parameters_raw("/some,dir/path,tip"))
 
517
        self.assertEqual(("/somedir/path", ["heads%2Ftip"]),
 
518
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
 
519
        self.assertEqual(("/somedir/path", ["heads%2Ftip", "bar"]),
 
520
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
 
521
        # Check relative references with relative paths
 
522
        self.assertEqual(("", ["key1=val1"]),
 
523
            split_segment_parameters_raw(",key1=val1"))
 
524
        self.assertEqual(("foo/", ["key1=val1"]),
 
525
            split_segment_parameters_raw("foo/,key1=val1"))
 
526
        self.assertEqual(("foo", ["key1=val1"]),
 
527
            split_segment_parameters_raw("foo,key1=val1"))
 
528
        self.assertEqual(("foo/base,la=bla/other/elements", []),
 
529
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
 
530
        self.assertEqual(("foo/base,la=bla/other/elements", ["a=b"]),
 
531
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
 
532
        # TODO: Check full URLs as well as relative references
 
533
 
 
534
    def test_split_segment_parameters(self):
 
535
        split_segment_parameters = urlutils.split_segment_parameters
 
536
        # Check relative references with absolute paths
 
537
        self.assertEqual(("/some/path", {}),
 
538
            split_segment_parameters("/some/path"))
 
539
        self.assertEqual(("/some/path", {"branch": "tip"}),
 
540
            split_segment_parameters("/some/path,branch=tip"))
 
541
        self.assertEqual(("/some,dir/path", {"branch": "tip"}),
 
542
            split_segment_parameters("/some,dir/path,branch=tip"))
 
543
        self.assertEqual(("/somedir/path", {"ref": "heads%2Ftip"}),
 
544
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
 
545
        self.assertEqual(("/somedir/path",
 
546
            {"ref": "heads%2Ftip", "key1": "val1"}),
 
547
            split_segment_parameters(
 
548
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
 
549
        self.assertEqual(("/somedir/path", {"ref": "heads%2F=tip"}),
 
550
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
 
551
        # Check relative references with relative paths
 
552
        self.assertEqual(("", {"key1": "val1"}),
 
553
            split_segment_parameters(",key1=val1"))
 
554
        self.assertEqual(("foo/", {"key1": "val1"}),
 
555
            split_segment_parameters("foo/,key1=val1"))
 
556
        self.assertEqual(("foo/base,key1=val1/other/elements", {}),
 
557
            split_segment_parameters("foo/base,key1=val1/other/elements"))
 
558
        self.assertEqual(("foo/base,key1=val1/other/elements",
 
559
            {"key2": "val2"}), split_segment_parameters(
 
560
                "foo/base,key1=val1/other/elements,key2=val2"))
 
561
        # TODO: Check full URLs as well as relative references
 
562
 
407
563
    def test_win32_strip_local_trailing_slash(self):
408
564
        strip = urlutils._win32_strip_local_trailing_slash
409
565
        self.assertEqual('file://', strip('file://'))
491
647
    def test_escape(self):
492
648
        self.assertEqual('%25', urlutils.escape('%'))
493
649
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
 
650
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
 
651
 
 
652
    def test_escape_tildes(self):
 
653
        self.assertEqual('~foo', urlutils.escape('~foo'))
494
654
 
495
655
    def test_unescape(self):
496
656
        self.assertEqual('%', urlutils.unescape('%25'))
508
668
        def test(expected, base, other):
509
669
            result = urlutils.relative_url(base, other)
510
670
            self.assertEqual(expected, result)
511
 
            
 
671
 
512
672
        test('a', 'http://host/', 'http://host/a')
513
673
        test('http://entirely/different', 'sftp://host/branch',
514
674
                    'http://entirely/different')
523
683
                    'sftp://host/home/jelmer/branch/2b')
524
684
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
525
685
                    'http://host/home/jelmer/branch/feature/%2b')
526
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
 
686
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
527
687
                    'http://host/home/jelmer/branch/feature/2b')
528
688
        # relative_url should preserve a trailing slash
529
689
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
541
701
        #test('.', 'http://host/', 'http://host')
542
702
        test('http://host', 'http://host/', 'http://host')
543
703
 
 
704
        # On Windows file:///C:/path/to and file:///D:/other/path
 
705
        # should not use relative url over the non-existent '/' directory.
 
706
        if sys.platform == 'win32':
 
707
            # on the same drive
 
708
            test('../../other/path',
 
709
                'file:///C:/path/to', 'file:///C:/other/path')
 
710
            #~next two tests is failed, i.e. urlutils.relative_url expects
 
711
            #~to see normalized file URLs?
 
712
            #~test('../../other/path',
 
713
            #~    'file:///C:/path/to', 'file:///c:/other/path')
 
714
            #~test('../../other/path',
 
715
            #~    'file:///C:/path/to', 'file:///C|/other/path')
 
716
 
 
717
            # check UNC paths too
 
718
            test('../../other/path',
 
719
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
 
720
            # on different drives
 
721
            test('file:///D:/other/path',
 
722
                'file:///C:/path/to', 'file:///D:/other/path')
 
723
            # TODO: strictly saying in UNC path //HOST/base is full analog
 
724
            # of drive letter for hard disk, and this situation is also
 
725
            # should be exception from rules. [bialix 20071221]
 
726
 
544
727
 
545
728
class TestCwdToURL(TestCaseInTempDir):
546
 
    """Test that local_path_to_url works base on the cwd"""
 
729
    """Test that local_path_to_url works based on the cwd"""
547
730
 
548
731
    def test_dot(self):
549
732
        # This test will fail if getcwd is not ascii
564
747
 
565
748
        os.chdir(u'dod\xe9')
566
749
 
567
 
        # On Mac OSX this directory is actually: 
 
750
        # On Mac OSX this directory is actually:
568
751
        #   u'/dode\u0301' => '/dode\xcc\x81
569
 
        # but we should normalize it back to 
 
752
        # but we should normalize it back to
570
753
        #   u'/dod\xe9' => '/dod\xc3\xa9'
571
754
        url = urlutils.local_path_to_url('.')
572
755
        self.assertEndsWith(url, '/dod%C3%A9')
588
771
        self.assertEqual("bar", derive("http://foo/bar"))
589
772
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
590
773
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
 
774
 
 
775
 
 
776
class TestRebaseURL(TestCase):
 
777
    """Test the behavior of rebase_url."""
 
778
 
 
779
    def test_non_relative(self):
 
780
        result = urlutils.rebase_url('file://foo', 'file://foo',
 
781
                                     'file://foo/bar')
 
782
        self.assertEqual('file://foo', result)
 
783
        result = urlutils.rebase_url('/foo', 'file://foo',
 
784
                                     'file://foo/bar')
 
785
        self.assertEqual('/foo', result)
 
786
 
 
787
    def test_different_ports(self):
 
788
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
789
                              'foo', 'http://bar:80', 'http://bar:81')
 
790
        self.assertEqual(str(e), "URLs differ by more than path:"
 
791
                         " 'http://bar:80' and 'http://bar:81'")
 
792
 
 
793
    def test_different_hosts(self):
 
794
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
795
                              'foo', 'http://bar', 'http://baz')
 
796
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
797
                         " and 'http://baz'")
 
798
 
 
799
    def test_different_protocol(self):
 
800
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
801
                              'foo', 'http://bar', 'ftp://bar')
 
802
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
803
                         " and 'ftp://bar'")
 
804
 
 
805
    def test_rebase_success(self):
 
806
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
 
807
                         'http://baz/qux'))
 
808
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
 
809
                         'http://baz/qux', 'http://baz/'))
 
810
        self.assertEqual('.', urlutils.rebase_url('foo',
 
811
                         'http://bar/', 'http://bar/foo/'))
 
812
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
 
813
                         'http://baz/qux/foo', 'http://baz/'))
 
814
 
 
815
    def test_determine_relative_path(self):
 
816
        self.assertEqual('../../baz/bar',
 
817
                         urlutils.determine_relative_path(
 
818
                         '/qux/quxx', '/baz/bar'))
 
819
        self.assertEqual('..',
 
820
                         urlutils.determine_relative_path(
 
821
                         '/bar/baz', '/bar'))
 
822
        self.assertEqual('baz',
 
823
                         urlutils.determine_relative_path(
 
824
                         '/bar', '/bar/baz'))
 
825
        self.assertEqual('.', urlutils.determine_relative_path(
 
826
                         '/bar', '/bar'))
 
827
 
 
828
 
 
829
class TestParseURL(TestCase):
 
830
 
 
831
    def test_parse_simple(self):
 
832
        parsed = urlutils.parse_url('http://example.com:80/one')
 
833
        self.assertEqual(('http', None, None, 'example.com', 80, '/one'),
 
834
            parsed)
 
835
 
 
836
    def test_ipv6(self):
 
837
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
 
838
        self.assertEqual(('http', None, None, '1:2:3::40', None, '/one'),
 
839
            parsed)
 
840
 
 
841
    def test_ipv6_port(self):
 
842
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
 
843
        self.assertEqual(('http', None, None, '1:2:3::40', 80, '/one'),
 
844
            parsed)
 
845
 
 
846
 
 
847
class TestURL(TestCase):
 
848
 
 
849
    def test_parse_simple(self):
 
850
        parsed = urlutils.URL.from_string('http://example.com:80/one')
 
851
        self.assertEqual('http', parsed.scheme)
 
852
        self.assertIs(None, parsed.user)
 
853
        self.assertIs(None, parsed.password)
 
854
        self.assertEqual('example.com', parsed.host)
 
855
        self.assertEqual(80, parsed.port)
 
856
        self.assertEqual('/one', parsed.path)
 
857
 
 
858
    def test_ipv6(self):
 
859
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
 
860
        self.assertEqual('http', parsed.scheme)
 
861
        self.assertIs(None, parsed.port)
 
862
        self.assertIs(None, parsed.user)
 
863
        self.assertIs(None, parsed.password)
 
864
        self.assertEqual('1:2:3::40', parsed.host)
 
865
        self.assertEqual('/one', parsed.path)
 
866
 
 
867
    def test_ipv6_port(self):
 
868
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
869
        self.assertEqual('http', parsed.scheme)
 
870
        self.assertEqual('1:2:3::40', parsed.host)
 
871
        self.assertIs(None, parsed.user)
 
872
        self.assertIs(None, parsed.password)
 
873
        self.assertEqual(80, parsed.port)
 
874
        self.assertEqual('/one', parsed.path)
 
875
 
 
876
    def test_quoted(self):
 
877
        parsed = urlutils.URL.from_string(
 
878
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
 
879
        self.assertEqual(parsed.quoted_host, 'ex%41mple.com')
 
880
        self.assertEqual(parsed.host, 'exAmple.com')
 
881
        self.assertEqual(parsed.port, 2222)
 
882
        self.assertEqual(parsed.quoted_user, 'ro%62ey')
 
883
        self.assertEqual(parsed.user, 'robey')
 
884
        self.assertEqual(parsed.quoted_password, 'h%40t')
 
885
        self.assertEqual(parsed.password, 'h@t')
 
886
        self.assertEqual(parsed.path, '/path')
 
887
 
 
888
    def test_eq(self):
 
889
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
890
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
891
        self.assertEqual(parsed1, parsed2)
 
892
        self.assertEqual(parsed1, parsed1)
 
893
        parsed2.path = '/two'
 
894
        self.assertNotEqual(parsed1, parsed2)
 
895
 
 
896
    def test_repr(self):
 
897
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
898
        self.assertEqual(
 
899
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
 
900
            repr(parsed))
 
901
 
 
902
    def test_str(self):
 
903
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
904
        self.assertEqual('http://[1:2:3::40]:80/one', str(parsed))
 
905
 
 
906
    def test__combine_paths(self):
 
907
        combine = urlutils.URL._combine_paths
 
908
        self.assertEqual('/home/sarah/project/foo',
 
909
                         combine('/home/sarah', 'project/foo'))
 
910
        self.assertEqual('/etc',
 
911
                         combine('/home/sarah', '../../etc'))
 
912
        self.assertEqual('/etc',
 
913
                         combine('/home/sarah', '../../../etc'))
 
914
        self.assertEqual('/etc',
 
915
                         combine('/home/sarah', '/etc'))
 
916
 
 
917
    def test_clone(self):
 
918
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
919
        url1 = url.clone("two")
 
920
        self.assertEqual("/one/two", url1.path)
 
921
        url2 = url.clone("/two")
 
922
        self.assertEqual("/two", url2.path)
 
923
        url3 = url.clone()
 
924
        self.assertIsNot(url, url3)
 
925
        self.assertEqual(url, url3)
 
926
 
 
927
 
 
928
class TestFileRelpath(TestCase):
 
929
 
 
930
    # GZ 2011-11-18: A way to override all path handling functions to one
 
931
    #                platform or another for testing would be nice.
 
932
 
 
933
    def _with_posix_paths(self):
 
934
        self.overrideAttr(urlutils, "local_path_from_url",
 
935
            urlutils._posix_local_path_from_url)
 
936
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH", len("file:///"))
 
937
        self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
 
938
        self.overrideAttr(osutils, "abspath", osutils._posix_abspath)
 
939
        self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
 
940
        self.overrideAttr(osutils, "pathjoin", osutils.posixpath.join)
 
941
        self.overrideAttr(osutils, "split", osutils.posixpath.split)
 
942
        self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 1)
 
943
 
 
944
    def _with_win32_paths(self):
 
945
        self.overrideAttr(urlutils, "local_path_from_url",
 
946
            urlutils._win32_local_path_from_url)
 
947
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH",
 
948
            urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
 
949
        self.overrideAttr(osutils, "abspath", osutils._win32_abspath)
 
950
        self.overrideAttr(osutils, "normpath", osutils._win32_normpath)
 
951
        self.overrideAttr(osutils, "pathjoin", osutils._win32_pathjoin)
 
952
        self.overrideAttr(osutils, "split", osutils.ntpath.split)
 
953
        self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 3)
 
954
 
 
955
    def test_same_url_posix(self):
 
956
        self._with_posix_paths()
 
957
        self.assertEqual("",
 
958
            urlutils.file_relpath("file:///a", "file:///a"))
 
959
        self.assertEqual("",
 
960
            urlutils.file_relpath("file:///a", "file:///a/"))
 
961
        self.assertEqual("",
 
962
            urlutils.file_relpath("file:///a/", "file:///a"))
 
963
 
 
964
    def test_same_url_win32(self):
 
965
        self._with_win32_paths()
 
966
        self.assertEqual("",
 
967
            urlutils.file_relpath("file:///A:/", "file:///A:/"))
 
968
        self.assertEqual("",
 
969
            urlutils.file_relpath("file:///A|/", "file:///A:/"))
 
970
        self.assertEqual("",
 
971
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
 
972
        self.assertEqual("",
 
973
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
 
974
        self.assertEqual("",
 
975
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
 
976
 
 
977
    def test_child_posix(self):
 
978
        self._with_posix_paths()
 
979
        self.assertEqual("b",
 
980
            urlutils.file_relpath("file:///a", "file:///a/b"))
 
981
        self.assertEqual("b",
 
982
            urlutils.file_relpath("file:///a/", "file:///a/b"))
 
983
        self.assertEqual("b/c",
 
984
            urlutils.file_relpath("file:///a", "file:///a/b/c"))
 
985
 
 
986
    def test_child_win32(self):
 
987
        self._with_win32_paths()
 
988
        self.assertEqual("b",
 
989
            urlutils.file_relpath("file:///A:/", "file:///A:/b"))
 
990
        self.assertEqual("b",
 
991
            urlutils.file_relpath("file:///A|/", "file:///A:/b"))
 
992
        self.assertEqual("c",
 
993
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
 
994
        self.assertEqual("c",
 
995
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
 
996
        self.assertEqual("c/d",
 
997
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
 
998
 
 
999
    def test_sibling_posix(self):
 
1000
        self._with_posix_paths()
 
1001
        self.assertRaises(PathNotChild,
 
1002
            urlutils.file_relpath, "file:///a/b", "file:///a/c")
 
1003
        self.assertRaises(PathNotChild,
 
1004
            urlutils.file_relpath, "file:///a/b/", "file:///a/c")
 
1005
        self.assertRaises(PathNotChild,
 
1006
            urlutils.file_relpath, "file:///a/b/", "file:///a/c/")
 
1007
 
 
1008
    def test_sibling_win32(self):
 
1009
        self._with_win32_paths()
 
1010
        self.assertRaises(PathNotChild,
 
1011
            urlutils.file_relpath, "file:///A:/b", "file:///A:/c")
 
1012
        self.assertRaises(PathNotChild,
 
1013
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c")
 
1014
        self.assertRaises(PathNotChild,
 
1015
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c/")
 
1016
 
 
1017
    def test_parent_posix(self):
 
1018
        self._with_posix_paths()
 
1019
        self.assertRaises(PathNotChild,
 
1020
            urlutils.file_relpath, "file:///a/b", "file:///a")
 
1021
        self.assertRaises(PathNotChild,
 
1022
            urlutils.file_relpath, "file:///a/b", "file:///a/")
 
1023
 
 
1024
    def test_parent_win32(self):
 
1025
        self._with_win32_paths()
 
1026
        self.assertRaises(PathNotChild,
 
1027
            urlutils.file_relpath, "file:///A:/b", "file:///A:/")
 
1028
        self.assertRaises(PathNotChild,
 
1029
            urlutils.file_relpath, "file:///A:/b/c", "file:///A:/b")
 
1030
 
 
1031
 
 
1032
class QuoteTests(TestCase):
 
1033
 
 
1034
    def test_quote(self):
 
1035
        self.assertEqual('abc%20def', urlutils.quote('abc def'))
 
1036
        self.assertEqual('abc%2Fdef', urlutils.quote('abc/def', safe=''))
 
1037
        self.assertEqual('abc/def', urlutils.quote('abc/def', safe='/'))
 
1038
 
 
1039
    def test_quote_tildes(self):
 
1040
        self.assertEqual('%7Efoo', urlutils.quote('~foo'))
 
1041
        self.assertEqual('~foo', urlutils.quote('~foo', safe='/~'))
 
1042
 
 
1043
    def test_unquote(self):
 
1044
        self.assertEqual('%', urlutils.unquote('%25'))
 
1045
        self.assertEqual('\xc3\xa5', urlutils.unquote('%C3%A5'))
 
1046
        self.assertEqual(u"\xe5", urlutils.unquote(u'\xe5'))