~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Martin Packman
  • Date: 2011-12-23 19:38:22 UTC
  • mto: This revision was merged to the branch mainline in revision 6405.
  • Revision ID: martin.packman@canonical.com-20111223193822-hesheea4o8aqwexv
Accept and document passing the medium rather than transport for smart connections

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
 
23
from bzrlib.errors import (
 
24
    InvalidURL,
 
25
    InvalidURLJoin,
 
26
    InvalidRebaseURLs,
 
27
    PathNotChild,
 
28
    )
26
29
from bzrlib.tests import 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.assertEquals("/somedir/path", 
 
300
            join_segment_parameters_raw("/somedir/path"))
 
301
        self.assertEquals("/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.assertEquals("/somedir/path,bla,bar",
 
307
            join_segment_parameters_raw("/somedir/path", "bla", "bar"))
 
308
        self.assertEquals("/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.assertEquals("/somedir/path", 
 
317
            join_segment_parameters("/somedir/path", {}))
 
318
        self.assertEquals("/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.assertEquals("/somedir/path,key1=val1,key2=val2",
 
326
            join_segment_parameters("/somedir/path", {
 
327
                "key1": "val1", "key2": "val2"}))
 
328
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
 
329
            join_segment_parameters("/somedir/path,key1=val1", {
 
330
                "key2": "val2"}))
 
331
        self.assertEquals("/somedir/path,key1=val2",
 
332
            join_segment_parameters("/somedir/path,key1=val1", {
 
333
                "key1": "val2"}))
 
334
        self.assertEquals("/somedir,exist=some/path,key1=val1",
 
335
            join_segment_parameters("/somedir,exist=some/path",
 
336
                {"key1": "val1"}))
 
337
        self.assertEquals("/,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):
327
414
        to_url = urlutils._win32_local_path_to_url
336
423
            raise TestSkipped("local encoding cannot handle unicode")
337
424
 
338
425
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
339
 
 
 
426
        self.assertFalse(isinstance(result, unicode))
340
427
 
341
428
    def test_win32_local_path_from_url(self):
342
429
        from_url = urlutils._win32_local_path_from_url
346
433
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
347
434
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
348
435
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
436
        self.assertEqual('/', from_url('file:///'))
 
437
        self.assertEqual('C:/path/to/foo',
 
438
            from_url('file:///C|/path/to/foo,branch=foo'))
349
439
 
 
440
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
 
441
        self.assertRaises(InvalidURL, from_url, 'file:///c')
350
442
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
351
443
        # Not a valid _win32 url, no drive letter
352
444
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
354
446
    def test_win32_unc_path_from_url(self):
355
447
        from_url = urlutils._win32_local_path_from_url
356
448
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
 
449
        self.assertEqual('//HOST/path',
 
450
            from_url('file://HOST/path,branch=foo'))
357
451
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
358
452
        # we want to use only 2 slashes
359
453
        # Firefox understand only 5 slashes in URL, but it's ugly
368
462
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
369
463
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
370
464
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
 
465
        # Root drives without slash treated as invalid, see bug #841322
 
466
        self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
 
467
        self.assertRaises(InvalidURL, extract, 'file://', '/C:')
 
468
        # Invalid without drive separator or following forward slash
 
469
        self.assertRaises(InvalidURL, extract, 'file://', '/C')
 
470
        self.assertRaises(InvalidURL, extract, 'file://', '/C:ool')
371
471
 
372
472
    def test_split(self):
373
473
        # Test bzrlib.urlutils.split()
404
504
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
405
505
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
406
506
 
 
507
    def test_split_segment_parameters_raw(self):
 
508
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
 
509
        # Check relative references with absolute paths
 
510
        self.assertEquals(("/some/path", []),
 
511
            split_segment_parameters_raw("/some/path"))
 
512
        self.assertEquals(("/some/path", ["tip"]),
 
513
            split_segment_parameters_raw("/some/path,tip"))
 
514
        self.assertEquals(("/some,dir/path", ["tip"]),
 
515
            split_segment_parameters_raw("/some,dir/path,tip"))
 
516
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
 
517
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
 
518
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
 
519
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
 
520
        # Check relative references with relative paths
 
521
        self.assertEquals(("", ["key1=val1"]),
 
522
            split_segment_parameters_raw(",key1=val1"))
 
523
        self.assertEquals(("foo/", ["key1=val1"]),
 
524
            split_segment_parameters_raw("foo/,key1=val1"))
 
525
        self.assertEquals(("foo", ["key1=val1"]),
 
526
            split_segment_parameters_raw("foo,key1=val1"))
 
527
        self.assertEquals(("foo/base,la=bla/other/elements", []),
 
528
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
 
529
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
 
530
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
 
531
        # TODO: Check full URLs as well as relative references
 
532
 
 
533
    def test_split_segment_parameters(self):
 
534
        split_segment_parameters = urlutils.split_segment_parameters
 
535
        # Check relative references with absolute paths
 
536
        self.assertEquals(("/some/path", {}),
 
537
            split_segment_parameters("/some/path"))
 
538
        self.assertEquals(("/some/path", {"branch": "tip"}),
 
539
            split_segment_parameters("/some/path,branch=tip"))
 
540
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
 
541
            split_segment_parameters("/some,dir/path,branch=tip"))
 
542
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
 
543
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
 
544
        self.assertEquals(("/somedir/path",
 
545
            {"ref": "heads%2Ftip", "key1": "val1"}),
 
546
            split_segment_parameters(
 
547
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
 
548
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
 
549
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
 
550
        # Check relative references with relative paths
 
551
        self.assertEquals(("", {"key1": "val1"}),
 
552
            split_segment_parameters(",key1=val1"))
 
553
        self.assertEquals(("foo/", {"key1": "val1"}),
 
554
            split_segment_parameters("foo/,key1=val1"))
 
555
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
 
556
            split_segment_parameters("foo/base,key1=val1/other/elements"))
 
557
        self.assertEquals(("foo/base,key1=val1/other/elements",
 
558
            {"key2": "val2"}), split_segment_parameters(
 
559
                "foo/base,key1=val1/other/elements,key2=val2"))
 
560
        # TODO: Check full URLs as well as relative references
 
561
 
407
562
    def test_win32_strip_local_trailing_slash(self):
408
563
        strip = urlutils._win32_strip_local_trailing_slash
409
564
        self.assertEqual('file://', strip('file://'))
491
646
    def test_escape(self):
492
647
        self.assertEqual('%25', urlutils.escape('%'))
493
648
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
 
649
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
 
650
 
 
651
    def test_escape_tildes(self):
 
652
        self.assertEqual('~foo', urlutils.escape('~foo'))
494
653
 
495
654
    def test_unescape(self):
496
655
        self.assertEqual('%', urlutils.unescape('%25'))
508
667
        def test(expected, base, other):
509
668
            result = urlutils.relative_url(base, other)
510
669
            self.assertEqual(expected, result)
511
 
            
 
670
 
512
671
        test('a', 'http://host/', 'http://host/a')
513
672
        test('http://entirely/different', 'sftp://host/branch',
514
673
                    'http://entirely/different')
523
682
                    'sftp://host/home/jelmer/branch/2b')
524
683
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
525
684
                    'http://host/home/jelmer/branch/feature/%2b')
526
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
 
685
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
527
686
                    'http://host/home/jelmer/branch/feature/2b')
528
687
        # relative_url should preserve a trailing slash
529
688
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
541
700
        #test('.', 'http://host/', 'http://host')
542
701
        test('http://host', 'http://host/', 'http://host')
543
702
 
 
703
        # On Windows file:///C:/path/to and file:///D:/other/path
 
704
        # should not use relative url over the non-existent '/' directory.
 
705
        if sys.platform == 'win32':
 
706
            # on the same drive
 
707
            test('../../other/path',
 
708
                'file:///C:/path/to', 'file:///C:/other/path')
 
709
            #~next two tests is failed, i.e. urlutils.relative_url expects
 
710
            #~to see normalized file URLs?
 
711
            #~test('../../other/path',
 
712
            #~    'file:///C:/path/to', 'file:///c:/other/path')
 
713
            #~test('../../other/path',
 
714
            #~    'file:///C:/path/to', 'file:///C|/other/path')
 
715
 
 
716
            # check UNC paths too
 
717
            test('../../other/path',
 
718
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
 
719
            # on different drives
 
720
            test('file:///D:/other/path',
 
721
                'file:///C:/path/to', 'file:///D:/other/path')
 
722
            # TODO: strictly saying in UNC path //HOST/base is full analog
 
723
            # of drive letter for hard disk, and this situation is also
 
724
            # should be exception from rules. [bialix 20071221]
 
725
 
544
726
 
545
727
class TestCwdToURL(TestCaseInTempDir):
546
728
    """Test that local_path_to_url works base on the cwd"""
564
746
 
565
747
        os.chdir(u'dod\xe9')
566
748
 
567
 
        # On Mac OSX this directory is actually: 
 
749
        # On Mac OSX this directory is actually:
568
750
        #   u'/dode\u0301' => '/dode\xcc\x81
569
 
        # but we should normalize it back to 
 
751
        # but we should normalize it back to
570
752
        #   u'/dod\xe9' => '/dod\xc3\xa9'
571
753
        url = urlutils.local_path_to_url('.')
572
754
        self.assertEndsWith(url, '/dod%C3%A9')
588
770
        self.assertEqual("bar", derive("http://foo/bar"))
589
771
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
590
772
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
 
773
 
 
774
 
 
775
class TestRebaseURL(TestCase):
 
776
    """Test the behavior of rebase_url."""
 
777
 
 
778
    def test_non_relative(self):
 
779
        result = urlutils.rebase_url('file://foo', 'file://foo',
 
780
                                     'file://foo/bar')
 
781
        self.assertEqual('file://foo', result)
 
782
        result = urlutils.rebase_url('/foo', 'file://foo',
 
783
                                     'file://foo/bar')
 
784
        self.assertEqual('/foo', result)
 
785
 
 
786
    def test_different_ports(self):
 
787
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
788
                              'foo', 'http://bar:80', 'http://bar:81')
 
789
        self.assertEqual(str(e), "URLs differ by more than path:"
 
790
                         " 'http://bar:80' and 'http://bar:81'")
 
791
 
 
792
    def test_different_hosts(self):
 
793
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
794
                              'foo', 'http://bar', 'http://baz')
 
795
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
796
                         " and 'http://baz'")
 
797
 
 
798
    def test_different_protocol(self):
 
799
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
800
                              'foo', 'http://bar', 'ftp://bar')
 
801
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
802
                         " and 'ftp://bar'")
 
803
 
 
804
    def test_rebase_success(self):
 
805
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
 
806
                         'http://baz/qux'))
 
807
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
 
808
                         'http://baz/qux', 'http://baz/'))
 
809
        self.assertEqual('.', urlutils.rebase_url('foo',
 
810
                         'http://bar/', 'http://bar/foo/'))
 
811
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
 
812
                         'http://baz/qux/foo', 'http://baz/'))
 
813
 
 
814
    def test_determine_relative_path(self):
 
815
        self.assertEqual('../../baz/bar',
 
816
                         urlutils.determine_relative_path(
 
817
                         '/qux/quxx', '/baz/bar'))
 
818
        self.assertEqual('..',
 
819
                         urlutils.determine_relative_path(
 
820
                         '/bar/baz', '/bar'))
 
821
        self.assertEqual('baz',
 
822
                         urlutils.determine_relative_path(
 
823
                         '/bar', '/bar/baz'))
 
824
        self.assertEqual('.', urlutils.determine_relative_path(
 
825
                         '/bar', '/bar'))
 
826
 
 
827
 
 
828
class TestParseURL(TestCase):
 
829
 
 
830
    def test_parse_simple(self):
 
831
        parsed = urlutils.parse_url('http://example.com:80/one')
 
832
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
 
833
            parsed)
 
834
 
 
835
    def test_ipv6(self):
 
836
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
 
837
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
 
838
            parsed)
 
839
 
 
840
    def test_ipv6_port(self):
 
841
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
 
842
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
 
843
            parsed)
 
844
 
 
845
 
 
846
class TestURL(TestCase):
 
847
 
 
848
    def test_parse_simple(self):
 
849
        parsed = urlutils.URL.from_string('http://example.com:80/one')
 
850
        self.assertEquals('http', parsed.scheme)
 
851
        self.assertIs(None, parsed.user)
 
852
        self.assertIs(None, parsed.password)
 
853
        self.assertEquals('example.com', parsed.host)
 
854
        self.assertEquals(80, parsed.port)
 
855
        self.assertEquals('/one', parsed.path)
 
856
 
 
857
    def test_ipv6(self):
 
858
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
 
859
        self.assertEquals('http', parsed.scheme)
 
860
        self.assertIs(None, parsed.port)
 
861
        self.assertIs(None, parsed.user)
 
862
        self.assertIs(None, parsed.password)
 
863
        self.assertEquals('1:2:3::40', parsed.host)
 
864
        self.assertEquals('/one', parsed.path)
 
865
 
 
866
    def test_ipv6_port(self):
 
867
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
868
        self.assertEquals('http', parsed.scheme)
 
869
        self.assertEquals('1:2:3::40', parsed.host)
 
870
        self.assertIs(None, parsed.user)
 
871
        self.assertIs(None, parsed.password)
 
872
        self.assertEquals(80, parsed.port)
 
873
        self.assertEquals('/one', parsed.path)
 
874
 
 
875
    def test_quoted(self):
 
876
        parsed = urlutils.URL.from_string(
 
877
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
 
878
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
 
879
        self.assertEquals(parsed.host, 'exAmple.com')
 
880
        self.assertEquals(parsed.port, 2222)
 
881
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
 
882
        self.assertEquals(parsed.user, 'robey')
 
883
        self.assertEquals(parsed.quoted_password, 'h%40t')
 
884
        self.assertEquals(parsed.password, 'h@t')
 
885
        self.assertEquals(parsed.path, '/path')
 
886
 
 
887
    def test_eq(self):
 
888
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
889
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
890
        self.assertEquals(parsed1, parsed2)
 
891
        self.assertEquals(parsed1, parsed1)
 
892
        parsed2.path = '/two'
 
893
        self.assertNotEquals(parsed1, parsed2)
 
894
 
 
895
    def test_repr(self):
 
896
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
897
        self.assertEquals(
 
898
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
 
899
            repr(parsed))
 
900
 
 
901
    def test_str(self):
 
902
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
903
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
 
904
 
 
905
    def test__combine_paths(self):
 
906
        combine = urlutils.URL._combine_paths
 
907
        self.assertEqual('/home/sarah/project/foo',
 
908
                         combine('/home/sarah', 'project/foo'))
 
909
        self.assertEqual('/etc',
 
910
                         combine('/home/sarah', '../../etc'))
 
911
        self.assertEqual('/etc',
 
912
                         combine('/home/sarah', '../../../etc'))
 
913
        self.assertEqual('/etc',
 
914
                         combine('/home/sarah', '/etc'))
 
915
 
 
916
    def test_clone(self):
 
917
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
 
918
        url1 = url.clone("two")
 
919
        self.assertEquals("/one/two", url1.path)
 
920
        url2 = url.clone("/two")
 
921
        self.assertEquals("/two", url2.path)
 
922
        url3 = url.clone()
 
923
        self.assertIsNot(url, url3)
 
924
        self.assertEquals(url, url3)
 
925
 
 
926
 
 
927
class TestFileRelpath(TestCase):
 
928
 
 
929
    # GZ 2011-11-18: A way to override all path handling functions to one
 
930
    #                platform or another for testing would be nice.
 
931
 
 
932
    def _with_posix_paths(self):
 
933
        self.overrideAttr(urlutils, "local_path_from_url",
 
934
            urlutils._posix_local_path_from_url)
 
935
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH", len("file:///"))
 
936
        self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
 
937
        self.overrideAttr(osutils, "abspath", osutils._posix_abspath)
 
938
        self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
 
939
        self.overrideAttr(osutils, "pathjoin", osutils.posixpath.join)
 
940
        self.overrideAttr(osutils, "split", osutils.posixpath.split)
 
941
        self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 1)
 
942
 
 
943
    def _with_win32_paths(self):
 
944
        self.overrideAttr(urlutils, "local_path_from_url",
 
945
            urlutils._win32_local_path_from_url)
 
946
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH",
 
947
            urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
 
948
        self.overrideAttr(osutils, "abspath", osutils._win32_abspath)
 
949
        self.overrideAttr(osutils, "normpath", osutils._win32_normpath)
 
950
        self.overrideAttr(osutils, "pathjoin", osutils._win32_pathjoin)
 
951
        self.overrideAttr(osutils, "split", osutils.ntpath.split)
 
952
        self.overrideAttr(osutils, "MIN_ABS_PATHLENGTH", 3)
 
953
 
 
954
    def test_same_url_posix(self):
 
955
        self._with_posix_paths()
 
956
        self.assertEquals("",
 
957
            urlutils.file_relpath("file:///a", "file:///a"))
 
958
        self.assertEquals("",
 
959
            urlutils.file_relpath("file:///a", "file:///a/"))
 
960
        self.assertEquals("",
 
961
            urlutils.file_relpath("file:///a/", "file:///a"))
 
962
 
 
963
    def test_same_url_win32(self):
 
964
        self._with_win32_paths()
 
965
        self.assertEquals("",
 
966
            urlutils.file_relpath("file:///A:/", "file:///A:/"))
 
967
        self.assertEquals("",
 
968
            urlutils.file_relpath("file:///A|/", "file:///A:/"))
 
969
        self.assertEquals("",
 
970
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
 
971
        self.assertEquals("",
 
972
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
 
973
        self.assertEquals("",
 
974
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
 
975
 
 
976
    def test_child_posix(self):
 
977
        self._with_posix_paths()
 
978
        self.assertEquals("b",
 
979
            urlutils.file_relpath("file:///a", "file:///a/b"))
 
980
        self.assertEquals("b",
 
981
            urlutils.file_relpath("file:///a/", "file:///a/b"))
 
982
        self.assertEquals("b/c",
 
983
            urlutils.file_relpath("file:///a", "file:///a/b/c"))
 
984
 
 
985
    def test_child_win32(self):
 
986
        self._with_win32_paths()
 
987
        self.assertEquals("b",
 
988
            urlutils.file_relpath("file:///A:/", "file:///A:/b"))
 
989
        self.assertEquals("b",
 
990
            urlutils.file_relpath("file:///A|/", "file:///A:/b"))
 
991
        self.assertEquals("c",
 
992
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
 
993
        self.assertEquals("c",
 
994
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
 
995
        self.assertEquals("c/d",
 
996
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
 
997
 
 
998
    def test_sibling_posix(self):
 
999
        self._with_posix_paths()
 
1000
        self.assertRaises(PathNotChild,
 
1001
            urlutils.file_relpath, "file:///a/b", "file:///a/c")
 
1002
        self.assertRaises(PathNotChild,
 
1003
            urlutils.file_relpath, "file:///a/b/", "file:///a/c")
 
1004
        self.assertRaises(PathNotChild,
 
1005
            urlutils.file_relpath, "file:///a/b/", "file:///a/c/")
 
1006
 
 
1007
    def test_sibling_win32(self):
 
1008
        self._with_win32_paths()
 
1009
        self.assertRaises(PathNotChild,
 
1010
            urlutils.file_relpath, "file:///A:/b", "file:///A:/c")
 
1011
        self.assertRaises(PathNotChild,
 
1012
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c")
 
1013
        self.assertRaises(PathNotChild,
 
1014
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c/")
 
1015
 
 
1016
    def test_parent_posix(self):
 
1017
        self._with_posix_paths()
 
1018
        self.assertRaises(PathNotChild,
 
1019
            urlutils.file_relpath, "file:///a/b", "file:///a")
 
1020
        self.assertRaises(PathNotChild,
 
1021
            urlutils.file_relpath, "file:///a/b", "file:///a/")
 
1022
 
 
1023
    def test_parent_win32(self):
 
1024
        self._with_win32_paths()
 
1025
        self.assertRaises(PathNotChild,
 
1026
            urlutils.file_relpath, "file:///A:/b", "file:///A:/")
 
1027
        self.assertRaises(PathNotChild,
 
1028
            urlutils.file_relpath, "file:///A:/b/c", "file:///A:/b")