~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Aaron Bentley
  • Date: 2008-09-23 17:00:03 UTC
  • mto: This revision was merged to the branch mainline in revision 3728.
  • Revision ID: aaron@aaronbentley.com-20080923170003-8vh06dg6jewct4ta
Correct spelling of 'Application Data'

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
 
24
import bzrlib
23
25
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
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:
366
297
        from_url = urlutils._posix_local_path_from_url
367
298
        self.assertEqual('/path/to/foo',
368
299
            from_url('file:///path/to/foo'))
369
 
        self.assertEqual('/path/to/foo',
370
 
            from_url('file:///path/to/foo,branch=foo'))
371
300
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
372
301
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
373
302
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
374
303
            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
304
 
378
305
        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
306
 
383
307
    def test_win32_local_path_to_url(self):
384
308
        to_url = urlutils._win32_local_path_to_url
392
316
        #     to_url('C:/path/to/foo '))
393
317
        self.assertEqual('file:///C:/path/to/f%20oo',
394
318
            to_url('C:/path/to/f oo'))
395
 
 
 
319
        
396
320
        self.assertEqual('file:///', to_url('/'))
397
321
 
398
 
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
399
 
            to_url('C:/path/to/foo,bar'))
400
322
        try:
401
323
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
402
324
        except UnicodeError:
429
351
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
430
352
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
431
353
        self.assertEqual('/', from_url('file:///'))
432
 
        self.assertEqual('C:/path/to/foo',
433
 
            from_url('file:///C|/path/to/foo,branch=foo'))
434
354
 
435
 
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
436
 
        self.assertRaises(InvalidURL, from_url, 'file:///c')
437
355
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
438
356
        # Not a valid _win32 url, no drive letter
439
357
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
441
359
    def test_win32_unc_path_from_url(self):
442
360
        from_url = urlutils._win32_local_path_from_url
443
361
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
444
 
        self.assertEqual('//HOST/path',
445
 
            from_url('file://HOST/path,branch=foo'))
446
362
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
447
363
        # we want to use only 2 slashes
448
364
        # Firefox understand only 5 slashes in URL, but it's ugly
457
373
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
458
374
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
459
375
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
460
 
        # Root drives without slash treated as invalid, see bug #841322
461
 
        self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
462
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:')
463
 
        # Invalid without drive separator or following forward slash
464
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C')
465
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:ool')
466
376
 
467
377
    def test_split(self):
468
378
        # Test bzrlib.urlutils.split()
499
409
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
500
410
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
501
411
 
502
 
    def test_split_segment_parameters_raw(self):
503
 
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
504
 
        self.assertEquals(("/some/path", []),
505
 
            split_segment_parameters_raw("/some/path"))
506
 
        self.assertEquals(("/some/path", ["tip"]),
507
 
            split_segment_parameters_raw("/some/path,tip"))
508
 
        self.assertEquals(("/some,dir/path", ["tip"]),
509
 
            split_segment_parameters_raw("/some,dir/path,tip"))
510
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
511
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
512
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
513
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
514
 
        self.assertEquals(("/", ["key1=val1"]),
515
 
            split_segment_parameters_raw(",key1=val1"))
516
 
        self.assertEquals(("foo/", ["key1=val1"]),
517
 
            split_segment_parameters_raw("foo/,key1=val1"))
518
 
        self.assertEquals(("/foo", ["key1=val1"]),
519
 
            split_segment_parameters_raw("foo,key1=val1"))
520
 
        self.assertEquals(("foo/base,la=bla/other/elements", []),
521
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
522
 
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
523
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
524
 
 
525
 
    def test_split_segment_parameters(self):
526
 
        split_segment_parameters = urlutils.split_segment_parameters
527
 
        self.assertEquals(("/some/path", {}),
528
 
            split_segment_parameters("/some/path"))
529
 
        self.assertEquals(("/some/path", {"branch": "tip"}),
530
 
            split_segment_parameters("/some/path,branch=tip"))
531
 
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
532
 
            split_segment_parameters("/some,dir/path,branch=tip"))
533
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
534
 
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
535
 
        self.assertEquals(("/somedir/path",
536
 
            {"ref": "heads%2Ftip", "key1": "val1"}),
537
 
            split_segment_parameters(
538
 
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
539
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
540
 
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
541
 
        self.assertEquals(("/", {"key1": "val1"}),
542
 
            split_segment_parameters(",key1=val1"))
543
 
        self.assertEquals(("foo/", {"key1": "val1"}),
544
 
            split_segment_parameters("foo/,key1=val1"))
545
 
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
546
 
            split_segment_parameters("foo/base,key1=val1/other/elements"))
547
 
        self.assertEquals(("foo/base,key1=val1/other/elements",
548
 
            {"key2": "val2"}), split_segment_parameters(
549
 
                "foo/base,key1=val1/other/elements,key2=val2"))
550
 
 
551
412
    def test_win32_strip_local_trailing_slash(self):
552
413
        strip = urlutils._win32_strip_local_trailing_slash
553
414
        self.assertEqual('file://', strip('file://'))
637
498
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
638
499
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
639
500
 
640
 
    def test_escape_tildes(self):
641
 
        self.assertEqual('~foo', urlutils.escape('~foo'))
642
 
 
643
501
    def test_unescape(self):
644
502
        self.assertEqual('%', urlutils.unescape('%25'))
645
503
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
656
514
        def test(expected, base, other):
657
515
            result = urlutils.relative_url(base, other)
658
516
            self.assertEqual(expected, result)
659
 
 
 
517
            
660
518
        test('a', 'http://host/', 'http://host/a')
661
519
        test('http://entirely/different', 'sftp://host/branch',
662
520
                    'http://entirely/different')
671
529
                    'sftp://host/home/jelmer/branch/2b')
672
530
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
673
531
                    'http://host/home/jelmer/branch/feature/%2b')
674
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
 
532
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
675
533
                    'http://host/home/jelmer/branch/feature/2b')
676
534
        # relative_url should preserve a trailing slash
677
535
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
735
593
 
736
594
        os.chdir(u'dod\xe9')
737
595
 
738
 
        # On Mac OSX this directory is actually:
 
596
        # On Mac OSX this directory is actually: 
739
597
        #   u'/dode\u0301' => '/dode\xcc\x81
740
 
        # but we should normalize it back to
 
598
        # but we should normalize it back to 
741
599
        #   u'/dod\xe9' => '/dod\xc3\xa9'
742
600
        url = urlutils.local_path_to_url('.')
743
601
        self.assertEndsWith(url, '/dod%C3%A9')
812
670
                         '/bar', '/bar/baz'))
813
671
        self.assertEqual('.', urlutils.determine_relative_path(
814
672
                         '/bar', '/bar'))
815
 
 
816
 
 
817
 
class TestParseURL(TestCase):
818
 
 
819
 
    def test_parse_simple(self):
820
 
        parsed = urlutils.parse_url('http://example.com:80/one')
821
 
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
822
 
            parsed)
823
 
 
824
 
    def test_ipv6(self):
825
 
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
826
 
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
827
 
            parsed)
828
 
 
829
 
    def test_ipv6_port(self):
830
 
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
831
 
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
832
 
            parsed)
833
 
 
834
 
 
835
 
class TestURL(TestCase):
836
 
 
837
 
    def test_parse_simple(self):
838
 
        parsed = urlutils.URL.from_string('http://example.com:80/one')
839
 
        self.assertEquals('http', parsed.scheme)
840
 
        self.assertIs(None, parsed.user)
841
 
        self.assertIs(None, parsed.password)
842
 
        self.assertEquals('example.com', parsed.host)
843
 
        self.assertEquals(80, parsed.port)
844
 
        self.assertEquals('/one', parsed.path)
845
 
 
846
 
    def test_ipv6(self):
847
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
848
 
        self.assertEquals('http', parsed.scheme)
849
 
        self.assertIs(None, parsed.port)
850
 
        self.assertIs(None, parsed.user)
851
 
        self.assertIs(None, parsed.password)
852
 
        self.assertEquals('1:2:3::40', parsed.host)
853
 
        self.assertEquals('/one', parsed.path)
854
 
 
855
 
    def test_ipv6_port(self):
856
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
857
 
        self.assertEquals('http', parsed.scheme)
858
 
        self.assertEquals('1:2:3::40', parsed.host)
859
 
        self.assertIs(None, parsed.user)
860
 
        self.assertIs(None, parsed.password)
861
 
        self.assertEquals(80, parsed.port)
862
 
        self.assertEquals('/one', parsed.path)
863
 
 
864
 
    def test_quoted(self):
865
 
        parsed = urlutils.URL.from_string(
866
 
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
867
 
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
868
 
        self.assertEquals(parsed.host, 'exAmple.com')
869
 
        self.assertEquals(parsed.port, 2222)
870
 
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
871
 
        self.assertEquals(parsed.user, 'robey')
872
 
        self.assertEquals(parsed.quoted_password, 'h%40t')
873
 
        self.assertEquals(parsed.password, 'h@t')
874
 
        self.assertEquals(parsed.path, '/path')
875
 
 
876
 
    def test_eq(self):
877
 
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
878
 
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
879
 
        self.assertEquals(parsed1, parsed2)
880
 
        self.assertEquals(parsed1, parsed1)
881
 
        parsed2.path = '/two'
882
 
        self.assertNotEquals(parsed1, parsed2)
883
 
 
884
 
    def test_repr(self):
885
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
886
 
        self.assertEquals(
887
 
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
888
 
            repr(parsed))
889
 
 
890
 
    def test_str(self):
891
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
892
 
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
893
 
 
894
 
    def test__combine_paths(self):
895
 
        combine = urlutils.URL._combine_paths
896
 
        self.assertEqual('/home/sarah/project/foo',
897
 
                         combine('/home/sarah', 'project/foo'))
898
 
        self.assertEqual('/etc',
899
 
                         combine('/home/sarah', '../../etc'))
900
 
        self.assertEqual('/etc',
901
 
                         combine('/home/sarah', '../../../etc'))
902
 
        self.assertEqual('/etc',
903
 
                         combine('/home/sarah', '/etc'))
904
 
 
905
 
    def test_clone(self):
906
 
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
907
 
        url1 = url.clone("two")
908
 
        self.assertEquals("/one/two", url1.path)
909
 
        url2 = url.clone("/two")
910
 
        self.assertEquals("/two", url2.path)
911
 
        url3 = url.clone()
912
 
        self.assertIsNot(url, url3)
913
 
        self.assertEquals(url, url3)