~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Martin Pool
  • Date: 2007-06-18 06:54:24 UTC
  • mto: This revision was merged to the branch mainline in revision 2551.
  • Revision ID: mbp@sourcefrog.net-20070618065424-awsn4t4tv2bi4okt
Remove duplicated commit use case documentation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Tests for the urlutils wrapper."""
18
18
 
19
19
import os
 
20
import re
20
21
import sys
21
22
 
22
23
from bzrlib import osutils, urlutils, win32utils
23
 
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
 
24
import bzrlib
 
25
from bzrlib.errors import InvalidURL, InvalidURLJoin
24
26
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
25
27
 
26
28
 
27
29
class TestUrlToPath(TestCase):
28
 
 
 
30
    
29
31
    def test_basename(self):
30
32
        # bzrlib.urlutils.basename
31
33
        # Test bzrlib.urlutils.split()
80
82
 
81
83
        # Local paths are assumed to *not* be escaped at all
82
84
        try:
83
 
            u'uni/\xb5'.encode(osutils.get_user_encoding())
 
85
            u'uni/\xb5'.encode(bzrlib.user_encoding)
84
86
        except UnicodeError:
85
 
            # locale cannot handle unicode
 
87
            # locale cannot handle unicode 
86
88
            pass
87
89
        else:
88
90
            norm_file('uni/%C2%B5', u'uni/\xb5')
156
158
        # Weird stuff
157
159
        # Can't have slashes or colons in the scheme
158
160
        test_one('/path/to/://foo', None)
159
 
        test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
 
161
        test_one('path:path://foo', None)
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'))
195
197
            dirname('path/to/foo/', exclude_trailing_slash=False))
196
198
        self.assertEqual('path/..', dirname('path/../foo'))
197
199
        self.assertEqual('../path', dirname('../path/foo'))
198
 
    
199
 
    def test_is_url(self):
200
 
        self.assertTrue(urlutils.is_url('http://foo/bar'))
201
 
        self.assertTrue(urlutils.is_url('bzr+ssh://foo/bar'))
202
 
        self.assertTrue(urlutils.is_url('lp:foo/bar'))
203
 
        self.assertTrue(urlutils.is_url('file:///foo/bar'))
204
 
        self.assertFalse(urlutils.is_url(''))
205
 
        self.assertFalse(urlutils.is_url('foo'))
206
 
        self.assertFalse(urlutils.is_url('foo/bar'))
207
 
        self.assertFalse(urlutils.is_url('/foo'))
208
 
        self.assertFalse(urlutils.is_url('/foo/bar'))
209
 
        self.assertFalse(urlutils.is_url('C:/'))
210
 
        self.assertFalse(urlutils.is_url('C:/foo'))
211
 
        self.assertFalse(urlutils.is_url('C:/foo/bar'))
212
200
 
213
201
    def test_join(self):
214
202
        def test(expected, *args):
224
212
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
225
213
        test('http://foo/baz', 'http://foo', 'bar/../baz')
226
214
        test('http://foo/baz', 'http://foo/bar/', '../baz')
227
 
        test('lp:foo/bar', 'lp:foo', 'bar')
228
 
        test('lp:foo/bar/baz', 'lp:foo', 'bar/baz')
229
215
 
230
216
        # Absolute paths
231
217
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
235
221
        test('http://bar/', 'http://foo', 'http://bar/')
236
222
        test('http://bar/a', 'http://foo', 'http://bar/a')
237
223
        test('http://bar/a/', 'http://foo', 'http://bar/a/')
238
 
        test('lp:bar', 'http://foo', 'lp:bar')
239
 
        test('lp:bar', 'lp:foo', 'lp:bar')
240
 
        test('file:///stuff', 'lp:foo', 'file:///stuff')
241
224
 
242
225
        # From a base path
243
226
        test('file:///foo', 'file:///', 'foo')
244
227
        test('file:///bar/foo', 'file:///bar/', 'foo')
245
228
        test('http://host/foo', 'http://host/', 'foo')
246
229
        test('http://host/', 'http://host', '')
247
 
 
 
230
        
248
231
        # Invalid joinings
249
232
        # Cannot go above root
250
233
        # Implicitly at root:
282
265
 
283
266
        # Test joining to a path with a trailing slash
284
267
        test('foo/bar', 'foo/', 'bar')
285
 
 
 
268
        
286
269
        # Invalid joinings
287
270
        # Cannot go above root
288
271
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
289
272
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
290
273
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
291
274
 
292
 
    def test_join_segment_parameters_raw(self):
293
 
        join_segment_parameters_raw = urlutils.join_segment_parameters_raw
294
 
        self.assertEquals("/somedir/path", 
295
 
            join_segment_parameters_raw("/somedir/path"))
296
 
        self.assertEquals("/somedir/path,rawdata", 
297
 
            join_segment_parameters_raw("/somedir/path", "rawdata"))
298
 
        self.assertRaises(InvalidURLJoin,
299
 
            join_segment_parameters_raw, "/somedir/path",
300
 
                "rawdata1,rawdata2,rawdata3")
301
 
        self.assertEquals("/somedir/path,bla,bar",
302
 
            join_segment_parameters_raw("/somedir/path", "bla", "bar"))
303
 
        self.assertEquals("/somedir,exist=some/path,bla,bar",
304
 
            join_segment_parameters_raw("/somedir,exist=some/path",
305
 
                "bla", "bar"))
306
 
        self.assertRaises(TypeError, join_segment_parameters_raw, 
307
 
            "/somepath", 42)
308
 
 
309
 
    def test_join_segment_parameters(self):
310
 
        join_segment_parameters = urlutils.join_segment_parameters
311
 
        self.assertEquals("/somedir/path", 
312
 
            join_segment_parameters("/somedir/path", {}))
313
 
        self.assertEquals("/somedir/path,key1=val1", 
314
 
            join_segment_parameters("/somedir/path", {"key1": "val1"}))
315
 
        self.assertRaises(InvalidURLJoin,
316
 
            join_segment_parameters, "/somedir/path",
317
 
            {"branch": "brr,brr,brr"})
318
 
        self.assertRaises(InvalidURLJoin,
319
 
            join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
320
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
321
 
            join_segment_parameters("/somedir/path", {
322
 
                "key1": "val1", "key2": "val2"}))
323
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
324
 
            join_segment_parameters("/somedir/path,key1=val1", {
325
 
                "key2": "val2"}))
326
 
        self.assertEquals("/somedir/path,key1=val2",
327
 
            join_segment_parameters("/somedir/path,key1=val1", {
328
 
                "key1": "val2"}))
329
 
        self.assertEquals("/somedir,exist=some/path,key1=val1",
330
 
            join_segment_parameters("/somedir,exist=some/path",
331
 
                {"key1": "val1"}))
332
 
        self.assertEquals("/,key1=val1,key2=val2",
333
 
            join_segment_parameters("/,key1=val1", {"key2": "val2"}))
334
 
        self.assertRaises(TypeError,
335
 
            join_segment_parameters, "/,key1=val1", {"foo": 42})
336
 
 
337
275
    def test_function_type(self):
338
276
        if sys.platform == 'win32':
339
 
            self.assertEqual(urlutils._win32_local_path_to_url,
340
 
                urlutils.local_path_to_url)
341
 
            self.assertEqual(urlutils._win32_local_path_from_url,
342
 
                urlutils.local_path_from_url)
 
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)
343
279
        else:
344
 
            self.assertEqual(urlutils._posix_local_path_to_url,
345
 
                urlutils.local_path_to_url)
346
 
            self.assertEqual(urlutils._posix_local_path_from_url,
347
 
                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)
348
282
 
349
283
    def test_posix_local_path_to_url(self):
350
284
        to_url = urlutils._posix_local_path_to_url
351
285
        self.assertEqual('file:///path/to/foo',
352
286
            to_url('/path/to/foo'))
353
287
 
354
 
        self.assertEqual('file:///path/to/foo%2Cbar',
355
 
            to_url('/path/to/foo,bar'))
356
 
 
357
288
        try:
358
289
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
359
290
        except UnicodeError:
360
291
            raise TestSkipped("local encoding cannot handle unicode")
361
292
 
362
293
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
363
 
        self.assertFalse(isinstance(result, unicode))
364
294
 
365
295
    def test_posix_local_path_from_url(self):
366
296
        from_url = urlutils._posix_local_path_from_url
367
297
        self.assertEqual('/path/to/foo',
368
298
            from_url('file:///path/to/foo'))
369
 
        self.assertEqual('/path/to/foo',
370
 
            from_url('file:///path/to/foo,branch=foo'))
371
299
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
372
300
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
373
301
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
374
302
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
375
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
376
 
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
377
303
 
378
304
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
379
 
        self.assertRaises(
380
 
            InvalidURL, from_url,
381
 
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
382
305
 
383
306
    def test_win32_local_path_to_url(self):
384
307
        to_url = urlutils._win32_local_path_to_url
393
316
        self.assertEqual('file:///C:/path/to/f%20oo',
394
317
            to_url('C:/path/to/f oo'))
395
318
 
396
 
        self.assertEqual('file:///', to_url('/'))
397
 
 
398
 
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
399
 
            to_url('C:/path/to/foo,bar'))
400
319
        try:
401
320
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
402
321
        except UnicodeError:
403
322
            raise TestSkipped("local encoding cannot handle unicode")
404
323
 
405
324
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
406
 
        self.assertFalse(isinstance(result, unicode))
407
325
 
408
326
    def test_win32_unc_path_to_url(self):
409
327
        to_url = urlutils._win32_local_path_to_url
418
336
            raise TestSkipped("local encoding cannot handle unicode")
419
337
 
420
338
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
421
 
        self.assertFalse(isinstance(result, unicode))
 
339
 
422
340
 
423
341
    def test_win32_local_path_from_url(self):
424
342
        from_url = urlutils._win32_local_path_from_url
428
346
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
429
347
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
430
348
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
431
 
        self.assertEqual('/', from_url('file:///'))
432
 
        self.assertEqual('C:/path/to/foo',
433
 
            from_url('file:///C|/path/to/foo,branch=foo'))
434
349
 
435
 
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
436
 
        self.assertRaises(InvalidURL, from_url, 'file:///c')
437
350
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
438
351
        # Not a valid _win32 url, no drive letter
439
352
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
441
354
    def test_win32_unc_path_from_url(self):
442
355
        from_url = urlutils._win32_local_path_from_url
443
356
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
444
 
        self.assertEqual('//HOST/path',
445
 
            from_url('file://HOST/path,branch=foo'))
446
357
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
447
358
        # we want to use only 2 slashes
448
359
        # Firefox understand only 5 slashes in URL, but it's ugly
493
404
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
494
405
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
495
406
 
496
 
    def test_split_segment_parameters_raw(self):
497
 
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
498
 
        self.assertEquals(("/some/path", []),
499
 
            split_segment_parameters_raw("/some/path"))
500
 
        self.assertEquals(("/some/path", ["tip"]),
501
 
            split_segment_parameters_raw("/some/path,tip"))
502
 
        self.assertEquals(("/some,dir/path", ["tip"]),
503
 
            split_segment_parameters_raw("/some,dir/path,tip"))
504
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
505
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
506
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
507
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
508
 
        self.assertEquals(("/", ["key1=val1"]),
509
 
            split_segment_parameters_raw(",key1=val1"))
510
 
        self.assertEquals(("foo/", ["key1=val1"]),
511
 
            split_segment_parameters_raw("foo/,key1=val1"))
512
 
        self.assertEquals(("/foo", ["key1=val1"]),
513
 
            split_segment_parameters_raw("foo,key1=val1"))
514
 
        self.assertEquals(("foo/base,la=bla/other/elements", []),
515
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
516
 
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
517
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
518
 
 
519
 
    def test_split_segment_parameters(self):
520
 
        split_segment_parameters = urlutils.split_segment_parameters
521
 
        self.assertEquals(("/some/path", {}),
522
 
            split_segment_parameters("/some/path"))
523
 
        self.assertEquals(("/some/path", {"branch": "tip"}),
524
 
            split_segment_parameters("/some/path,branch=tip"))
525
 
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
526
 
            split_segment_parameters("/some,dir/path,branch=tip"))
527
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
528
 
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
529
 
        self.assertEquals(("/somedir/path",
530
 
            {"ref": "heads%2Ftip", "key1": "val1"}),
531
 
            split_segment_parameters(
532
 
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
533
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
534
 
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
535
 
        self.assertEquals(("/", {"key1": "val1"}),
536
 
            split_segment_parameters(",key1=val1"))
537
 
        self.assertEquals(("foo/", {"key1": "val1"}),
538
 
            split_segment_parameters("foo/,key1=val1"))
539
 
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
540
 
            split_segment_parameters("foo/base,key1=val1/other/elements"))
541
 
        self.assertEquals(("foo/base,key1=val1/other/elements",
542
 
            {"key2": "val2"}), split_segment_parameters(
543
 
                "foo/base,key1=val1/other/elements,key2=val2"))
544
 
 
545
407
    def test_win32_strip_local_trailing_slash(self):
546
408
        strip = urlutils._win32_strip_local_trailing_slash
547
409
        self.assertEqual('file://', strip('file://'))
629
491
    def test_escape(self):
630
492
        self.assertEqual('%25', urlutils.escape('%'))
631
493
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
632
 
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
633
 
 
634
 
    def test_escape_tildes(self):
635
 
        self.assertEqual('~foo', urlutils.escape('~foo'))
636
494
 
637
495
    def test_unescape(self):
638
496
        self.assertEqual('%', urlutils.unescape('%25'))
650
508
        def test(expected, base, other):
651
509
            result = urlutils.relative_url(base, other)
652
510
            self.assertEqual(expected, result)
653
 
 
 
511
            
654
512
        test('a', 'http://host/', 'http://host/a')
655
513
        test('http://entirely/different', 'sftp://host/branch',
656
514
                    'http://entirely/different')
665
523
                    'sftp://host/home/jelmer/branch/2b')
666
524
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
667
525
                    'http://host/home/jelmer/branch/feature/%2b')
668
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
 
526
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
669
527
                    'http://host/home/jelmer/branch/feature/2b')
670
528
        # relative_url should preserve a trailing slash
671
529
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
683
541
        #test('.', 'http://host/', 'http://host')
684
542
        test('http://host', 'http://host/', 'http://host')
685
543
 
686
 
        # On Windows file:///C:/path/to and file:///D:/other/path
687
 
        # should not use relative url over the non-existent '/' directory.
688
 
        if sys.platform == 'win32':
689
 
            # on the same drive
690
 
            test('../../other/path',
691
 
                'file:///C:/path/to', 'file:///C:/other/path')
692
 
            #~next two tests is failed, i.e. urlutils.relative_url expects
693
 
            #~to see normalized file URLs?
694
 
            #~test('../../other/path',
695
 
            #~    'file:///C:/path/to', 'file:///c:/other/path')
696
 
            #~test('../../other/path',
697
 
            #~    'file:///C:/path/to', 'file:///C|/other/path')
698
 
 
699
 
            # check UNC paths too
700
 
            test('../../other/path',
701
 
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
702
 
            # on different drives
703
 
            test('file:///D:/other/path',
704
 
                'file:///C:/path/to', 'file:///D:/other/path')
705
 
            # TODO: strictly saying in UNC path //HOST/base is full analog
706
 
            # of drive letter for hard disk, and this situation is also
707
 
            # should be exception from rules. [bialix 20071221]
708
 
 
709
544
 
710
545
class TestCwdToURL(TestCaseInTempDir):
711
546
    """Test that local_path_to_url works base on the cwd"""
729
564
 
730
565
        os.chdir(u'dod\xe9')
731
566
 
732
 
        # On Mac OSX this directory is actually:
 
567
        # On Mac OSX this directory is actually: 
733
568
        #   u'/dode\u0301' => '/dode\xcc\x81
734
 
        # but we should normalize it back to
 
569
        # but we should normalize it back to 
735
570
        #   u'/dod\xe9' => '/dod\xc3\xa9'
736
571
        url = urlutils.local_path_to_url('.')
737
572
        self.assertEndsWith(url, '/dod%C3%A9')
738
 
 
739
 
 
740
 
class TestDeriveToLocation(TestCase):
741
 
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
742
 
 
743
 
    def test_to_locations_derived_from_paths(self):
744
 
        derive = urlutils.derive_to_location
745
 
        self.assertEqual("bar", derive("bar"))
746
 
        self.assertEqual("bar", derive("../bar"))
747
 
        self.assertEqual("bar", derive("/foo/bar"))
748
 
        self.assertEqual("bar", derive("c:/foo/bar"))
749
 
        self.assertEqual("bar", derive("c:bar"))
750
 
 
751
 
    def test_to_locations_derived_from_urls(self):
752
 
        derive = urlutils.derive_to_location
753
 
        self.assertEqual("bar", derive("http://foo/bar"))
754
 
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
755
 
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
756
 
 
757
 
 
758
 
class TestRebaseURL(TestCase):
759
 
    """Test the behavior of rebase_url."""
760
 
 
761
 
    def test_non_relative(self):
762
 
        result = urlutils.rebase_url('file://foo', 'file://foo',
763
 
                                     'file://foo/bar')
764
 
        self.assertEqual('file://foo', result)
765
 
        result = urlutils.rebase_url('/foo', 'file://foo',
766
 
                                     'file://foo/bar')
767
 
        self.assertEqual('/foo', result)
768
 
 
769
 
    def test_different_ports(self):
770
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
771
 
                              'foo', 'http://bar:80', 'http://bar:81')
772
 
        self.assertEqual(str(e), "URLs differ by more than path:"
773
 
                         " 'http://bar:80' and 'http://bar:81'")
774
 
 
775
 
    def test_different_hosts(self):
776
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
777
 
                              'foo', 'http://bar', 'http://baz')
778
 
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
779
 
                         " and 'http://baz'")
780
 
 
781
 
    def test_different_protocol(self):
782
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
783
 
                              'foo', 'http://bar', 'ftp://bar')
784
 
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
785
 
                         " and 'ftp://bar'")
786
 
 
787
 
    def test_rebase_success(self):
788
 
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
789
 
                         'http://baz/qux'))
790
 
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
791
 
                         'http://baz/qux', 'http://baz/'))
792
 
        self.assertEqual('.', urlutils.rebase_url('foo',
793
 
                         'http://bar/', 'http://bar/foo/'))
794
 
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
795
 
                         'http://baz/qux/foo', 'http://baz/'))
796
 
 
797
 
    def test_determine_relative_path(self):
798
 
        self.assertEqual('../../baz/bar',
799
 
                         urlutils.determine_relative_path(
800
 
                         '/qux/quxx', '/baz/bar'))
801
 
        self.assertEqual('..',
802
 
                         urlutils.determine_relative_path(
803
 
                         '/bar/baz', '/bar'))
804
 
        self.assertEqual('baz',
805
 
                         urlutils.determine_relative_path(
806
 
                         '/bar', '/bar/baz'))
807
 
        self.assertEqual('.', urlutils.determine_relative_path(
808
 
                         '/bar', '/bar'))
809
 
 
810
 
 
811
 
class TestParseURL(TestCase):
812
 
 
813
 
    def test_parse_simple(self):
814
 
        parsed = urlutils.parse_url('http://example.com:80/one')
815
 
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
816
 
            parsed)
817
 
 
818
 
    def test_ipv6(self):
819
 
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
820
 
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
821
 
            parsed)
822
 
 
823
 
    def test_ipv6_port(self):
824
 
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
825
 
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
826
 
            parsed)
827
 
 
828
 
 
829
 
class TestURL(TestCase):
830
 
 
831
 
    def test_parse_simple(self):
832
 
        parsed = urlutils.URL.from_string('http://example.com:80/one')
833
 
        self.assertEquals('http', parsed.scheme)
834
 
        self.assertIs(None, parsed.user)
835
 
        self.assertIs(None, parsed.password)
836
 
        self.assertEquals('example.com', parsed.host)
837
 
        self.assertEquals(80, parsed.port)
838
 
        self.assertEquals('/one', parsed.path)
839
 
 
840
 
    def test_ipv6(self):
841
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
842
 
        self.assertEquals('http', parsed.scheme)
843
 
        self.assertIs(None, parsed.port)
844
 
        self.assertIs(None, parsed.user)
845
 
        self.assertIs(None, parsed.password)
846
 
        self.assertEquals('1:2:3::40', parsed.host)
847
 
        self.assertEquals('/one', parsed.path)
848
 
 
849
 
    def test_ipv6_port(self):
850
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
851
 
        self.assertEquals('http', parsed.scheme)
852
 
        self.assertEquals('1:2:3::40', parsed.host)
853
 
        self.assertIs(None, parsed.user)
854
 
        self.assertIs(None, parsed.password)
855
 
        self.assertEquals(80, parsed.port)
856
 
        self.assertEquals('/one', parsed.path)
857
 
 
858
 
    def test_quoted(self):
859
 
        parsed = urlutils.URL.from_string(
860
 
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
861
 
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
862
 
        self.assertEquals(parsed.host, 'exAmple.com')
863
 
        self.assertEquals(parsed.port, 2222)
864
 
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
865
 
        self.assertEquals(parsed.user, 'robey')
866
 
        self.assertEquals(parsed.quoted_password, 'h%40t')
867
 
        self.assertEquals(parsed.password, 'h@t')
868
 
        self.assertEquals(parsed.path, '/path')
869
 
 
870
 
    def test_eq(self):
871
 
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
872
 
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
873
 
        self.assertEquals(parsed1, parsed2)
874
 
        self.assertEquals(parsed1, parsed1)
875
 
        parsed2.path = '/two'
876
 
        self.assertNotEquals(parsed1, parsed2)
877
 
 
878
 
    def test_repr(self):
879
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
880
 
        self.assertEquals(
881
 
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
882
 
            repr(parsed))
883
 
 
884
 
    def test_str(self):
885
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
886
 
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
887
 
 
888
 
    def test__combine_paths(self):
889
 
        combine = urlutils.URL._combine_paths
890
 
        self.assertEqual('/home/sarah/project/foo',
891
 
                         combine('/home/sarah', 'project/foo'))
892
 
        self.assertEqual('/etc',
893
 
                         combine('/home/sarah', '../../etc'))
894
 
        self.assertEqual('/etc',
895
 
                         combine('/home/sarah', '../../../etc'))
896
 
        self.assertEqual('/etc',
897
 
                         combine('/home/sarah', '/etc'))
898
 
 
899
 
    def test_clone(self):
900
 
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
901
 
        url1 = url.clone("two")
902
 
        self.assertEquals("/one/two", url1.path)
903
 
        url2 = url.clone("/two")
904
 
        self.assertEquals("/two", url2.path)
905
 
        url3 = url.clone()
906
 
        self.assertIsNot(url, url3)
907
 
        self.assertEquals(url, url3)