~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-02-05 11:33:58 UTC
  • mfrom: (5008.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100205113358-wd4d49omal1hus75
(vila) Add --take-this and --take-other actions to bzr resolve

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the urlutils wrapper."""
18
18
 
19
19
import os
20
 
import re
21
20
import sys
22
21
 
23
 
from bzrlib import osutils, urlutils
24
 
import bzrlib
25
 
from bzrlib.errors import InvalidURL, InvalidURLJoin
 
22
from bzrlib import osutils, urlutils, win32utils
 
23
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
26
24
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
27
25
 
28
26
 
29
27
class TestUrlToPath(TestCase):
30
 
    
 
28
 
31
29
    def test_basename(self):
32
30
        # bzrlib.urlutils.basename
33
31
        # Test bzrlib.urlutils.split()
82
80
 
83
81
        # Local paths are assumed to *not* be escaped at all
84
82
        try:
85
 
            u'uni/\xb5'.encode(bzrlib.user_encoding)
 
83
            u'uni/\xb5'.encode(osutils.get_user_encoding())
86
84
        except UnicodeError:
87
 
            # locale cannot handle unicode 
 
85
            # locale cannot handle unicode
88
86
            pass
89
87
        else:
90
88
            norm_file('uni/%C2%B5', u'uni/\xb5')
115
113
        eq('http://host/ab/%C2%B5/%C2%B5',
116
114
            normalize_url(u'http://host/ab/%C2%B5/\xb5'))
117
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
 
118
122
        # Normalize verifies URLs when they are not unicode
119
123
        # (indicating they did not come from the user)
120
124
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
197
201
            joined = urlutils.join(*args)
198
202
            self.assertEqual(expected, joined)
199
203
 
200
 
        # Test a single element
201
 
        test('foo', 'foo')
202
 
 
203
204
        # Test relative path joining
 
205
        test('foo', 'foo') # relative fragment with nothing is preserved.
204
206
        test('foo/bar', 'foo', 'bar')
205
207
        test('http://foo/bar', 'http://foo', 'bar')
206
208
        test('http://foo/bar', 'http://foo', '.', 'bar')
207
209
        test('http://foo/baz', 'http://foo', 'bar', '../baz')
208
210
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
209
211
        test('http://foo/baz', 'http://foo', 'bar/../baz')
 
212
        test('http://foo/baz', 'http://foo/bar/', '../baz')
210
213
 
211
214
        # Absolute paths
 
215
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
212
216
        test('http://bar', 'http://foo', 'http://bar')
213
217
        test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
214
218
        test('file:///bar', 'foo', 'file:///bar')
 
219
        test('http://bar/', 'http://foo', 'http://bar/')
 
220
        test('http://bar/a', 'http://foo', 'http://bar/a')
 
221
        test('http://bar/a/', 'http://foo', 'http://bar/a/')
215
222
 
216
223
        # From a base path
217
224
        test('file:///foo', 'file:///', 'foo')
218
225
        test('file:///bar/foo', 'file:///bar/', 'foo')
219
226
        test('http://host/foo', 'http://host/', 'foo')
220
227
        test('http://host/', 'http://host', '')
221
 
        
 
228
 
222
229
        # Invalid joinings
223
230
        # Cannot go above root
 
231
        # Implicitly at root:
224
232
        self.assertRaises(InvalidURLJoin, urlutils.join,
225
233
                'http://foo', '../baz')
 
234
        self.assertRaises(InvalidURLJoin, urlutils.join,
 
235
                'http://foo', '/..')
 
236
        # Joining from a path explicitly under the root.
 
237
        self.assertRaises(InvalidURLJoin, urlutils.join,
 
238
                'http://foo/a', '../../b')
 
239
 
 
240
    def test_joinpath(self):
 
241
        def test(expected, *args):
 
242
            joined = urlutils.joinpath(*args)
 
243
            self.assertEqual(expected, joined)
 
244
 
 
245
        # Test a single element
 
246
        test('foo', 'foo')
 
247
 
 
248
        # Test relative path joining
 
249
        test('foo/bar', 'foo', 'bar')
 
250
        test('foo/bar', 'foo', '.', 'bar')
 
251
        test('foo/baz', 'foo', 'bar', '../baz')
 
252
        test('foo/bar/baz', 'foo', 'bar/baz')
 
253
        test('foo/baz', 'foo', 'bar/../baz')
 
254
 
 
255
        # Test joining to an absolute path
 
256
        test('/foo', '/foo')
 
257
        test('/foo', '/foo', '.')
 
258
        test('/foo/bar', '/foo', 'bar')
 
259
        test('/', '/foo', '..')
 
260
 
 
261
        # Test joining with an absolute path
 
262
        test('/bar', 'foo', '/bar')
 
263
 
 
264
        # Test joining to a path with a trailing slash
 
265
        test('foo/bar', 'foo/', 'bar')
 
266
 
 
267
        # Invalid joinings
 
268
        # Cannot go above root
 
269
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
 
270
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
 
271
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
226
272
 
227
273
    def test_function_type(self):
228
274
        if sys.platform == 'win32':
243
289
            raise TestSkipped("local encoding cannot handle unicode")
244
290
 
245
291
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
292
        self.assertFalse(isinstance(result, unicode))
246
293
 
247
294
    def test_posix_local_path_from_url(self):
248
295
        from_url = urlutils._posix_local_path_from_url
252
299
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
253
300
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
254
301
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
302
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
 
303
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
255
304
 
256
305
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
 
306
        self.assertRaises(
 
307
            InvalidURL, from_url,
 
308
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
257
309
 
258
310
    def test_win32_local_path_to_url(self):
259
311
        to_url = urlutils._win32_local_path_to_url
268
320
        self.assertEqual('file:///C:/path/to/f%20oo',
269
321
            to_url('C:/path/to/f oo'))
270
322
 
 
323
        self.assertEqual('file:///', to_url('/'))
 
324
 
271
325
        try:
272
326
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
273
327
        except UnicodeError:
274
328
            raise TestSkipped("local encoding cannot handle unicode")
275
329
 
276
330
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
331
        self.assertFalse(isinstance(result, unicode))
 
332
 
 
333
    def test_win32_unc_path_to_url(self):
 
334
        to_url = urlutils._win32_local_path_to_url
 
335
        self.assertEqual('file://HOST/path',
 
336
            to_url(r'\\HOST\path'))
 
337
        self.assertEqual('file://HOST/path',
 
338
            to_url('//HOST/path'))
 
339
 
 
340
        try:
 
341
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
 
342
        except UnicodeError:
 
343
            raise TestSkipped("local encoding cannot handle unicode")
 
344
 
 
345
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
346
        self.assertFalse(isinstance(result, unicode))
277
347
 
278
348
    def test_win32_local_path_from_url(self):
279
349
        from_url = urlutils._win32_local_path_from_url
283
353
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
284
354
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
285
355
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
356
        self.assertEqual('/', from_url('file:///'))
286
357
 
287
358
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
288
359
        # Not a valid _win32 url, no drive letter
289
360
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
290
361
 
291
 
    def test__win32_extract_drive_letter(self):
 
362
    def test_win32_unc_path_from_url(self):
 
363
        from_url = urlutils._win32_local_path_from_url
 
364
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
 
365
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
 
366
        # we want to use only 2 slashes
 
367
        # Firefox understand only 5 slashes in URL, but it's ugly
 
368
        self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
 
369
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
 
370
        self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
 
371
        # check for file://C:/ instead of file:///C:/
 
372
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
 
373
 
 
374
    def test_win32_extract_drive_letter(self):
292
375
        extract = urlutils._win32_extract_drive_letter
293
376
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
294
377
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
329
412
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
330
413
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
331
414
 
332
 
    def test__win32_strip_local_trailing_slash(self):
 
415
    def test_win32_strip_local_trailing_slash(self):
333
416
        strip = urlutils._win32_strip_local_trailing_slash
334
417
        self.assertEqual('file://', strip('file://'))
335
418
        self.assertEqual('file:///', strip('file:///'))
416
499
    def test_escape(self):
417
500
        self.assertEqual('%25', urlutils.escape('%'))
418
501
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
 
502
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
 
503
 
 
504
    def test_escape_tildes(self):
 
505
        self.assertEqual('~foo', urlutils.escape('~foo'))
419
506
 
420
507
    def test_unescape(self):
421
508
        self.assertEqual('%', urlutils.unescape('%25'))
433
520
        def test(expected, base, other):
434
521
            result = urlutils.relative_url(base, other)
435
522
            self.assertEqual(expected, result)
436
 
            
 
523
 
437
524
        test('a', 'http://host/', 'http://host/a')
438
525
        test('http://entirely/different', 'sftp://host/branch',
439
526
                    'http://entirely/different')
448
535
                    'sftp://host/home/jelmer/branch/2b')
449
536
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
450
537
                    'http://host/home/jelmer/branch/feature/%2b')
451
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
 
538
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
452
539
                    'http://host/home/jelmer/branch/feature/2b')
453
540
        # relative_url should preserve a trailing slash
454
541
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
466
553
        #test('.', 'http://host/', 'http://host')
467
554
        test('http://host', 'http://host/', 'http://host')
468
555
 
 
556
        # On Windows file:///C:/path/to and file:///D:/other/path
 
557
        # should not use relative url over the non-existent '/' directory.
 
558
        if sys.platform == 'win32':
 
559
            # on the same drive
 
560
            test('../../other/path',
 
561
                'file:///C:/path/to', 'file:///C:/other/path')
 
562
            #~next two tests is failed, i.e. urlutils.relative_url expects
 
563
            #~to see normalized file URLs?
 
564
            #~test('../../other/path',
 
565
            #~    'file:///C:/path/to', 'file:///c:/other/path')
 
566
            #~test('../../other/path',
 
567
            #~    'file:///C:/path/to', 'file:///C|/other/path')
 
568
 
 
569
            # check UNC paths too
 
570
            test('../../other/path',
 
571
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
 
572
            # on different drives
 
573
            test('file:///D:/other/path',
 
574
                'file:///C:/path/to', 'file:///D:/other/path')
 
575
            # TODO: strictly saying in UNC path //HOST/base is full analog
 
576
            # of drive letter for hard disk, and this situation is also
 
577
            # should be exception from rules. [bialix 20071221]
 
578
 
469
579
 
470
580
class TestCwdToURL(TestCaseInTempDir):
471
581
    """Test that local_path_to_url works base on the cwd"""
479
589
        self.assertEndsWith(url, '/mytest')
480
590
 
481
591
    def test_non_ascii(self):
 
592
        if win32utils.winver == 'Windows 98':
 
593
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
 
594
 
482
595
        try:
483
596
            os.mkdir(u'dod\xe9')
484
597
        except UnicodeError:
486
599
 
487
600
        os.chdir(u'dod\xe9')
488
601
 
489
 
        # On Mac OSX this directory is actually: 
 
602
        # On Mac OSX this directory is actually:
490
603
        #   u'/dode\u0301' => '/dode\xcc\x81
491
 
        # but we should normalize it back to 
 
604
        # but we should normalize it back to
492
605
        #   u'/dod\xe9' => '/dod\xc3\xa9'
493
606
        url = urlutils.local_path_to_url('.')
494
607
        self.assertEndsWith(url, '/dod%C3%A9')
 
608
 
 
609
 
 
610
class TestDeriveToLocation(TestCase):
 
611
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
 
612
 
 
613
    def test_to_locations_derived_from_paths(self):
 
614
        derive = urlutils.derive_to_location
 
615
        self.assertEqual("bar", derive("bar"))
 
616
        self.assertEqual("bar", derive("../bar"))
 
617
        self.assertEqual("bar", derive("/foo/bar"))
 
618
        self.assertEqual("bar", derive("c:/foo/bar"))
 
619
        self.assertEqual("bar", derive("c:bar"))
 
620
 
 
621
    def test_to_locations_derived_from_urls(self):
 
622
        derive = urlutils.derive_to_location
 
623
        self.assertEqual("bar", derive("http://foo/bar"))
 
624
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
 
625
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
 
626
 
 
627
 
 
628
class TestRebaseURL(TestCase):
 
629
    """Test the behavior of rebase_url."""
 
630
 
 
631
    def test_non_relative(self):
 
632
        result = urlutils.rebase_url('file://foo', 'file://foo',
 
633
                                     'file://foo/bar')
 
634
        self.assertEqual('file://foo', result)
 
635
        result = urlutils.rebase_url('/foo', 'file://foo',
 
636
                                     'file://foo/bar')
 
637
        self.assertEqual('/foo', result)
 
638
 
 
639
    def test_different_ports(self):
 
640
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
641
                              'foo', 'http://bar:80', 'http://bar:81')
 
642
        self.assertEqual(str(e), "URLs differ by more than path:"
 
643
                         " 'http://bar:80' and 'http://bar:81'")
 
644
 
 
645
    def test_different_hosts(self):
 
646
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
647
                              'foo', 'http://bar', 'http://baz')
 
648
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
649
                         " and 'http://baz'")
 
650
 
 
651
    def test_different_protocol(self):
 
652
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
653
                              'foo', 'http://bar', 'ftp://bar')
 
654
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
 
655
                         " and 'ftp://bar'")
 
656
 
 
657
    def test_rebase_success(self):
 
658
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
 
659
                         'http://baz/qux'))
 
660
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
 
661
                         'http://baz/qux', 'http://baz/'))
 
662
        self.assertEqual('.', urlutils.rebase_url('foo',
 
663
                         'http://bar/', 'http://bar/foo/'))
 
664
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
 
665
                         'http://baz/qux/foo', 'http://baz/'))
 
666
 
 
667
    def test_determine_relative_path(self):
 
668
        self.assertEqual('../../baz/bar',
 
669
                         urlutils.determine_relative_path(
 
670
                         '/qux/quxx', '/baz/bar'))
 
671
        self.assertEqual('..',
 
672
                         urlutils.determine_relative_path(
 
673
                         '/bar/baz', '/bar'))
 
674
        self.assertEqual('baz',
 
675
                         urlutils.determine_relative_path(
 
676
                         '/bar', '/bar/baz'))
 
677
        self.assertEqual('.', urlutils.determine_relative_path(
 
678
                         '/bar', '/bar'))
 
679
 
 
680
 
 
681
class TestParseURL(TestCase):
 
682
 
 
683
    def test_parse_url(self):
 
684
        self.assertEqual(urlutils.parse_url('http://example.com:80/one'),
 
685
            ('http', None, None, 'example.com', 80, '/one'))
 
686
        self.assertEqual(urlutils.parse_url('http://[1:2:3::40]/one'),
 
687
                ('http', None, None, '1:2:3::40', None, '/one'))
 
688
        self.assertEqual(urlutils.parse_url('http://[1:2:3::40]:80/one'),
 
689
                ('http', None, None, '1:2:3::40', 80, '/one'))