~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: 2011-09-22 14:12:18 UTC
  • mfrom: (6155.3.1 jam)
  • Revision ID: pqm@pqm.ubuntu.com-20110922141218-86s4uu6nqvourw4f
(jameinel) Cleanup comments bzrlib/smart/__init__.py (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by 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
20
import sys
21
21
 
22
 
import bzrlib
23
 
from bzrlib.errors import InvalidURL, InvalidURLJoin
24
 
import bzrlib.urlutils as urlutils
 
22
from bzrlib import osutils, urlutils, win32utils
 
23
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
25
24
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
26
25
 
27
26
 
28
27
class TestUrlToPath(TestCase):
29
 
    
 
28
 
30
29
    def test_basename(self):
31
30
        # bzrlib.urlutils.basename
32
31
        # Test bzrlib.urlutils.split()
81
80
 
82
81
        # Local paths are assumed to *not* be escaped at all
83
82
        try:
84
 
            u'uni/\xb5'.encode(bzrlib.user_encoding)
 
83
            u'uni/\xb5'.encode(osutils.get_user_encoding())
85
84
        except UnicodeError:
86
 
            # locale cannot handle unicode 
 
85
            # locale cannot handle unicode
87
86
            pass
88
87
        else:
89
88
            norm_file('uni/%C2%B5', u'uni/\xb5')
114
113
        eq('http://host/ab/%C2%B5/%C2%B5',
115
114
            normalize_url(u'http://host/ab/%C2%B5/\xb5'))
116
115
 
 
116
        # Unescape characters that don't need to be escaped
 
117
        eq('http://host/~bob%2525-._',
 
118
                normalize_url('http://host/%7Ebob%2525%2D%2E%5F'))
 
119
        eq('http://host/~bob%2525-._',
 
120
                normalize_url(u'http://host/%7Ebob%2525%2D%2E%5F'))
 
121
 
117
122
        # Normalize verifies URLs when they are not unicode
118
123
        # (indicating they did not come from the user)
119
124
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
151
156
        # Weird stuff
152
157
        # Can't have slashes or colons in the scheme
153
158
        test_one('/path/to/://foo', None)
154
 
        test_one('path:path://foo', None)
 
159
        test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
155
160
        # Must have more than one character for scheme
156
161
        test_one('C://foo', None)
157
162
        test_one('ab://foo', ('ab', 'foo'))
190
195
            dirname('path/to/foo/', exclude_trailing_slash=False))
191
196
        self.assertEqual('path/..', dirname('path/../foo'))
192
197
        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'))
193
212
 
194
213
    def test_join(self):
195
214
        def test(expected, *args):
196
215
            joined = urlutils.join(*args)
197
216
            self.assertEqual(expected, joined)
198
217
 
199
 
        # Test a single element
200
 
        test('foo', 'foo')
201
 
 
202
218
        # Test relative path joining
 
219
        test('foo', 'foo') # relative fragment with nothing is preserved.
203
220
        test('foo/bar', 'foo', 'bar')
204
221
        test('http://foo/bar', 'http://foo', 'bar')
205
222
        test('http://foo/bar', 'http://foo', '.', 'bar')
206
223
        test('http://foo/baz', 'http://foo', 'bar', '../baz')
207
224
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
208
225
        test('http://foo/baz', 'http://foo', 'bar/../baz')
 
226
        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')
209
229
 
210
230
        # Absolute paths
 
231
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
211
232
        test('http://bar', 'http://foo', 'http://bar')
212
233
        test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
213
234
        test('file:///bar', 'foo', 'file:///bar')
214
 
        
 
235
        test('http://bar/', 'http://foo', 'http://bar/')
 
236
        test('http://bar/a', 'http://foo', 'http://bar/a')
 
237
        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
 
 
242
        # From a base path
 
243
        test('file:///foo', 'file:///', 'foo')
 
244
        test('file:///bar/foo', 'file:///bar/', 'foo')
 
245
        test('http://host/foo', 'http://host/', 'foo')
 
246
        test('http://host/', 'http://host', '')
 
247
 
215
248
        # Invalid joinings
216
249
        # Cannot go above root
 
250
        # Implicitly at root:
217
251
        self.assertRaises(InvalidURLJoin, urlutils.join,
218
252
                'http://foo', '../baz')
 
253
        self.assertRaises(InvalidURLJoin, urlutils.join,
 
254
                'http://foo', '/..')
 
255
        # Joining from a path explicitly under the root.
 
256
        self.assertRaises(InvalidURLJoin, urlutils.join,
 
257
                'http://foo/a', '../../b')
 
258
 
 
259
    def test_joinpath(self):
 
260
        def test(expected, *args):
 
261
            joined = urlutils.joinpath(*args)
 
262
            self.assertEqual(expected, joined)
 
263
 
 
264
        # Test a single element
 
265
        test('foo', 'foo')
 
266
 
 
267
        # Test relative path joining
 
268
        test('foo/bar', 'foo', 'bar')
 
269
        test('foo/bar', 'foo', '.', 'bar')
 
270
        test('foo/baz', 'foo', 'bar', '../baz')
 
271
        test('foo/bar/baz', 'foo', 'bar/baz')
 
272
        test('foo/baz', 'foo', 'bar/../baz')
 
273
 
 
274
        # Test joining to an absolute path
 
275
        test('/foo', '/foo')
 
276
        test('/foo', '/foo', '.')
 
277
        test('/foo/bar', '/foo', 'bar')
 
278
        test('/', '/foo', '..')
 
279
 
 
280
        # Test joining with an absolute path
 
281
        test('/bar', 'foo', '/bar')
 
282
 
 
283
        # Test joining to a path with a trailing slash
 
284
        test('foo/bar', 'foo/', 'bar')
 
285
 
 
286
        # Invalid joinings
 
287
        # Cannot go above root
 
288
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
 
289
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
 
290
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
 
291
 
 
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})
219
336
 
220
337
    def test_function_type(self):
221
338
        if sys.platform == 'win32':
222
 
            self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
223
 
            self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
 
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)
224
343
        else:
225
 
            self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
226
 
            self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
 
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)
227
348
 
228
349
    def test_posix_local_path_to_url(self):
229
350
        to_url = urlutils._posix_local_path_to_url
230
351
        self.assertEqual('file:///path/to/foo',
231
352
            to_url('/path/to/foo'))
232
353
 
 
354
        self.assertEqual('file:///path/to/foo%2Cbar',
 
355
            to_url('/path/to/foo,bar'))
 
356
 
233
357
        try:
234
358
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
235
359
        except UnicodeError:
236
360
            raise TestSkipped("local encoding cannot handle unicode")
237
361
 
238
362
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
363
        self.assertFalse(isinstance(result, unicode))
239
364
 
240
365
    def test_posix_local_path_from_url(self):
241
366
        from_url = urlutils._posix_local_path_from_url
242
367
        self.assertEqual('/path/to/foo',
243
368
            from_url('file:///path/to/foo'))
 
369
        self.assertEqual('/path/to/foo',
 
370
            from_url('file:///path/to/foo,branch=foo'))
244
371
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
245
372
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
246
373
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
247
374
            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'))
248
377
 
249
378
        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')
250
382
 
251
383
    def test_win32_local_path_to_url(self):
252
384
        to_url = urlutils._win32_local_path_to_url
261
393
        self.assertEqual('file:///C:/path/to/f%20oo',
262
394
            to_url('C:/path/to/f oo'))
263
395
 
 
396
        self.assertEqual('file:///', to_url('/'))
 
397
 
 
398
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
 
399
            to_url('C:/path/to/foo,bar'))
264
400
        try:
265
401
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
266
402
        except UnicodeError:
267
403
            raise TestSkipped("local encoding cannot handle unicode")
268
404
 
269
405
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
406
        self.assertFalse(isinstance(result, unicode))
 
407
 
 
408
    def test_win32_unc_path_to_url(self):
 
409
        to_url = urlutils._win32_local_path_to_url
 
410
        self.assertEqual('file://HOST/path',
 
411
            to_url(r'\\HOST\path'))
 
412
        self.assertEqual('file://HOST/path',
 
413
            to_url('//HOST/path'))
 
414
 
 
415
        try:
 
416
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
 
417
        except UnicodeError:
 
418
            raise TestSkipped("local encoding cannot handle unicode")
 
419
 
 
420
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
421
        self.assertFalse(isinstance(result, unicode))
270
422
 
271
423
    def test_win32_local_path_from_url(self):
272
424
        from_url = urlutils._win32_local_path_from_url
276
428
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
277
429
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
278
430
            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'))
279
434
 
 
435
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
 
436
        self.assertRaises(InvalidURL, from_url, 'file:///c')
280
437
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
281
438
        # Not a valid _win32 url, no drive letter
282
439
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
283
440
 
 
441
    def test_win32_unc_path_from_url(self):
 
442
        from_url = urlutils._win32_local_path_from_url
 
443
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
 
444
        self.assertEqual('//HOST/path',
 
445
            from_url('file://HOST/path,branch=foo'))
 
446
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
 
447
        # we want to use only 2 slashes
 
448
        # Firefox understand only 5 slashes in URL, but it's ugly
 
449
        self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
 
450
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
 
451
        self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
 
452
        # check for file://C:/ instead of file:///C:/
 
453
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
 
454
 
 
455
    def test_win32_extract_drive_letter(self):
 
456
        extract = urlutils._win32_extract_drive_letter
 
457
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
 
458
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
 
459
        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
 
284
467
    def test_split(self):
285
468
        # Test bzrlib.urlutils.split()
286
469
        split = urlutils.split
316
499
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
317
500
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
318
501
 
 
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
    def test_win32_strip_local_trailing_slash(self):
 
552
        strip = urlutils._win32_strip_local_trailing_slash
 
553
        self.assertEqual('file://', strip('file://'))
 
554
        self.assertEqual('file:///', strip('file:///'))
 
555
        self.assertEqual('file:///C', strip('file:///C'))
 
556
        self.assertEqual('file:///C:', strip('file:///C:'))
 
557
        self.assertEqual('file:///d|', strip('file:///d|'))
 
558
        self.assertEqual('file:///C:/', strip('file:///C:/'))
 
559
        self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
 
560
 
319
561
    def test_strip_trailing_slash(self):
320
562
        sts = urlutils.strip_trailing_slash
321
563
        if sys.platform == 'win32':
393
635
    def test_escape(self):
394
636
        self.assertEqual('%25', urlutils.escape('%'))
395
637
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
 
638
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
 
639
 
 
640
    def test_escape_tildes(self):
 
641
        self.assertEqual('~foo', urlutils.escape('~foo'))
396
642
 
397
643
    def test_unescape(self):
398
644
        self.assertEqual('%', urlutils.unescape('%25'))
410
656
        def test(expected, base, other):
411
657
            result = urlutils.relative_url(base, other)
412
658
            self.assertEqual(expected, result)
413
 
            
 
659
 
414
660
        test('a', 'http://host/', 'http://host/a')
415
661
        test('http://entirely/different', 'sftp://host/branch',
416
662
                    'http://entirely/different')
425
671
                    'sftp://host/home/jelmer/branch/2b')
426
672
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
427
673
                    'http://host/home/jelmer/branch/feature/%2b')
428
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
 
674
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
429
675
                    'http://host/home/jelmer/branch/feature/2b')
430
676
        # relative_url should preserve a trailing slash
431
677
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
442
688
        test('http://host/', 'http://host', 'http://host/')
443
689
        #test('.', 'http://host/', 'http://host')
444
690
        test('http://host', 'http://host/', 'http://host')
 
691
 
 
692
        # On Windows file:///C:/path/to and file:///D:/other/path
 
693
        # should not use relative url over the non-existent '/' directory.
 
694
        if sys.platform == 'win32':
 
695
            # on the same drive
 
696
            test('../../other/path',
 
697
                'file:///C:/path/to', 'file:///C:/other/path')
 
698
            #~next two tests is failed, i.e. urlutils.relative_url expects
 
699
            #~to see normalized file URLs?
 
700
            #~test('../../other/path',
 
701
            #~    'file:///C:/path/to', 'file:///c:/other/path')
 
702
            #~test('../../other/path',
 
703
            #~    'file:///C:/path/to', 'file:///C|/other/path')
 
704
 
 
705
            # check UNC paths too
 
706
            test('../../other/path',
 
707
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
 
708
            # on different drives
 
709
            test('file:///D:/other/path',
 
710
                'file:///C:/path/to', 'file:///D:/other/path')
 
711
            # TODO: strictly saying in UNC path //HOST/base is full analog
 
712
            # of drive letter for hard disk, and this situation is also
 
713
            # should be exception from rules. [bialix 20071221]
 
714
 
 
715
 
 
716
class TestCwdToURL(TestCaseInTempDir):
 
717
    """Test that local_path_to_url works base on the cwd"""
 
718
 
 
719
    def test_dot(self):
 
720
        # This test will fail if getcwd is not ascii
 
721
        os.mkdir('mytest')
 
722
        os.chdir('mytest')
 
723
 
 
724
        url = urlutils.local_path_to_url('.')
 
725
        self.assertEndsWith(url, '/mytest')
 
726
 
 
727
    def test_non_ascii(self):
 
728
        if win32utils.winver == 'Windows 98':
 
729
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
 
730
 
 
731
        try:
 
732
            os.mkdir(u'dod\xe9')
 
733
        except UnicodeError:
 
734
            raise TestSkipped('cannot create unicode directory')
 
735
 
 
736
        os.chdir(u'dod\xe9')
 
737
 
 
738
        # On Mac OSX this directory is actually:
 
739
        #   u'/dode\u0301' => '/dode\xcc\x81
 
740
        # but we should normalize it back to
 
741
        #   u'/dod\xe9' => '/dod\xc3\xa9'
 
742
        url = urlutils.local_path_to_url('.')
 
743
        self.assertEndsWith(url, '/dod%C3%A9')
 
744
 
 
745
 
 
746
class TestDeriveToLocation(TestCase):
 
747
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
 
748
 
 
749
    def test_to_locations_derived_from_paths(self):
 
750
        derive = urlutils.derive_to_location
 
751
        self.assertEqual("bar", derive("bar"))
 
752
        self.assertEqual("bar", derive("../bar"))
 
753
        self.assertEqual("bar", derive("/foo/bar"))
 
754
        self.assertEqual("bar", derive("c:/foo/bar"))
 
755
        self.assertEqual("bar", derive("c:bar"))
 
756
 
 
757
    def test_to_locations_derived_from_urls(self):
 
758
        derive = urlutils.derive_to_location
 
759
        self.assertEqual("bar", derive("http://foo/bar"))
 
760
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
 
761
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
 
762
 
 
763
 
 
764
class TestRebaseURL(TestCase):
 
765
    """Test the behavior of rebase_url."""
 
766
 
 
767
    def test_non_relative(self):
 
768
        result = urlutils.rebase_url('file://foo', 'file://foo',
 
769
                                     'file://foo/bar')
 
770
        self.assertEqual('file://foo', result)
 
771
        result = urlutils.rebase_url('/foo', 'file://foo',
 
772
                                     'file://foo/bar')
 
773
        self.assertEqual('/foo', result)
 
774
 
 
775
    def test_different_ports(self):
 
776
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
777
                              'foo', 'http://bar:80', 'http://bar:81')
 
778
        self.assertEqual(str(e), "URLs differ by more than path:"
 
779
                         " 'http://bar:80' and 'http://bar:81'")
 
780
 
 
781
    def test_different_hosts(self):
 
782
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
783
                              'foo', 'http://bar', 'http://baz')
 
784
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
785
                         " and 'http://baz'")
 
786
 
 
787
    def test_different_protocol(self):
 
788
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
789
                              'foo', 'http://bar', 'ftp://bar')
 
790
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
791
                         " and 'ftp://bar'")
 
792
 
 
793
    def test_rebase_success(self):
 
794
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
 
795
                         'http://baz/qux'))
 
796
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
 
797
                         'http://baz/qux', 'http://baz/'))
 
798
        self.assertEqual('.', urlutils.rebase_url('foo',
 
799
                         'http://bar/', 'http://bar/foo/'))
 
800
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
 
801
                         'http://baz/qux/foo', 'http://baz/'))
 
802
 
 
803
    def test_determine_relative_path(self):
 
804
        self.assertEqual('../../baz/bar',
 
805
                         urlutils.determine_relative_path(
 
806
                         '/qux/quxx', '/baz/bar'))
 
807
        self.assertEqual('..',
 
808
                         urlutils.determine_relative_path(
 
809
                         '/bar/baz', '/bar'))
 
810
        self.assertEqual('baz',
 
811
                         urlutils.determine_relative_path(
 
812
                         '/bar', '/bar/baz'))
 
813
        self.assertEqual('.', urlutils.determine_relative_path(
 
814
                         '/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)