~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-11 01:17:15 UTC
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061011011715-cead1acd0ee04372
Update HACKING and TODO

Show diffs side-by-side

added added

removed removed

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