/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_urlutils.py

  • Committer: Breezy landing bot
  • Author(s): Colin Watson
  • Date: 2020-11-16 21:47:08 UTC
  • mfrom: (7521.1.1 remove-lp-workaround)
  • Revision ID: breezy.the.bot@gmail.com-20201116214708-jos209mgxi41oy15
Remove breezy.git workaround for bazaar.launchpad.net.

Merged from https://code.launchpad.net/~cjwatson/brz/remove-lp-workaround/+merge/393710

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2012, 2015 Canonical Ltd
 
1
# Copyright (C) 2006-2012, 2015, 2016 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
19
19
import os
20
20
import sys
21
21
 
22
 
from bzrlib import osutils, urlutils, win32utils
23
 
from bzrlib.errors import (
24
 
    InvalidURL,
25
 
    InvalidURLJoin,
26
 
    InvalidRebaseURLs,
 
22
from .. import osutils, urlutils
 
23
from ..errors import (
27
24
    PathNotChild,
28
25
    )
29
 
from bzrlib.tests import features, TestCaseInTempDir, TestCase, TestSkipped
 
26
from . import features, TestCaseInTempDir, TestCase, TestSkipped
30
27
 
31
28
 
32
29
class TestUrlToPath(TestCase):
33
30
 
34
31
    def test_basename(self):
35
 
        # bzrlib.urlutils.basename
36
 
        # Test bzrlib.urlutils.split()
 
32
        # breezy.urlutils.basename
 
33
        # Test breezy.urlutils.split()
37
34
        basename = urlutils.basename
38
35
        if sys.platform == 'win32':
39
 
            self.assertRaises(InvalidURL, basename, 'file:///path/to/foo')
 
36
            self.assertRaises(urlutils.InvalidURL, basename,
 
37
                              'file:///path/to/foo')
40
38
            self.assertEqual('foo', basename('file:///C|/foo'))
41
39
            self.assertEqual('foo', basename('file:///C:/foo'))
42
40
            self.assertEqual('', basename('file:///C:/'))
46
44
 
47
45
        self.assertEqual('foo', basename('http://host/path/to/foo'))
48
46
        self.assertEqual('foo', basename('http://host/path/to/foo/'))
49
 
        self.assertEqual('',
50
 
            basename('http://host/path/to/foo/', exclude_trailing_slash=False))
 
47
        self.assertEqual(
 
48
            '', basename('http://host/path/to/foo/',
 
49
                         exclude_trailing_slash=False))
51
50
        self.assertEqual('path', basename('http://host/path'))
52
51
        self.assertEqual('', basename('http://host/'))
53
52
        self.assertEqual('', basename('http://host'))
54
53
        self.assertEqual('path', basename('http:///nohost/path'))
55
54
 
56
 
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path'))
57
 
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path/'))
 
55
        self.assertEqual('path', basename(
 
56
            'random+scheme://user:pass@ahost:port/path'))
 
57
        self.assertEqual('path', basename(
 
58
            'random+scheme://user:pass@ahost:port/path/'))
58
59
        self.assertEqual('', basename('random+scheme://user:pass@ahost:port/'))
59
60
 
60
61
        # relative paths
61
62
        self.assertEqual('foo', basename('path/to/foo'))
62
63
        self.assertEqual('foo', basename('path/to/foo/'))
63
64
        self.assertEqual('', basename('path/to/foo/',
64
 
            exclude_trailing_slash=False))
 
65
                                      exclude_trailing_slash=False))
65
66
        self.assertEqual('foo', basename('path/../foo'))
66
67
        self.assertEqual('foo', basename('../path/foo'))
67
68
 
120
121
 
121
122
        # Unescape characters that don't need to be escaped
122
123
        eq('http://host/~bob%2525-._',
123
 
                normalize_url('http://host/%7Ebob%2525%2D%2E%5F'))
 
124
           normalize_url('http://host/%7Ebob%2525%2D%2E%5F'))
124
125
        eq('http://host/~bob%2525-._',
125
 
                normalize_url(u'http://host/%7Ebob%2525%2D%2E%5F'))
126
 
 
127
 
        # Normalize verifies URLs when they are not unicode
128
 
        # (indicating they did not come from the user)
129
 
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
130
 
        self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
 
126
           normalize_url(u'http://host/%7Ebob%2525%2D%2E%5F'))
131
127
 
132
128
    def test_url_scheme_re(self):
133
129
        # Test paths that may be URLs
156
152
        test_one('file:///usr/bin', ('file', '/usr/bin'))
157
153
        test_one('file:///C:/Windows', ('file', '/C:/Windows'))
158
154
        test_one('file:///C|/Windows', ('file', '/C|/Windows'))
159
 
        test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
 
155
        test_one(u'readonly+sftp://host/path/\xe5',
 
156
                 ('readonly+sftp', u'host/path/\xe5'))
160
157
 
161
158
        # Weird stuff
162
159
        # Can't have slashes or colons in the scheme
167
164
        test_one('ab://foo', ('ab', 'foo'))
168
165
 
169
166
    def test_dirname(self):
170
 
        # Test bzrlib.urlutils.dirname()
 
167
        # Test breezy.urlutils.dirname()
171
168
        dirname = urlutils.dirname
172
169
        if sys.platform == 'win32':
173
 
            self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
 
170
            self.assertRaises(urlutils.InvalidURL, dirname,
 
171
                              'file:///path/to/foo')
174
172
            self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
175
173
            self.assertEqual('file:///C|/', dirname('file:///C|/'))
176
174
        else:
177
175
            self.assertEqual('file:///', dirname('file:///foo'))
178
176
            self.assertEqual('file:///', dirname('file:///'))
179
177
 
180
 
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
181
 
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
 
178
        self.assertEqual('http://host/path/to',
 
179
                         dirname('http://host/path/to/foo'))
 
180
        self.assertEqual('http://host/path/to',
 
181
                         dirname('http://host/path/to/foo/'))
182
182
        self.assertEqual('http://host/path/to/foo',
183
 
            dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
 
183
                         dirname('http://host/path/to/foo/',
 
184
                                 exclude_trailing_slash=False))
184
185
        self.assertEqual('http://host/', dirname('http://host/path'))
185
186
        self.assertEqual('http://host/', dirname('http://host/'))
186
187
        self.assertEqual('http://host', dirname('http://host'))
187
188
        self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
188
189
 
189
190
        self.assertEqual('random+scheme://user:pass@ahost:port/',
190
 
            dirname('random+scheme://user:pass@ahost:port/path'))
191
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
192
 
            dirname('random+scheme://user:pass@ahost:port/path/'))
193
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
194
 
            dirname('random+scheme://user:pass@ahost:port/'))
 
191
                         dirname('random+scheme://user:pass@ahost:port/path'))
 
192
        self.assertEqual('random+scheme://user:pass@ahost:port/',
 
193
                         dirname('random+scheme://user:pass@ahost:port/path/'))
 
194
        self.assertEqual('random+scheme://user:pass@ahost:port/',
 
195
                         dirname('random+scheme://user:pass@ahost:port/'))
195
196
 
196
197
        # relative paths
197
198
        self.assertEqual('path/to', dirname('path/to/foo'))
198
199
        self.assertEqual('path/to', dirname('path/to/foo/'))
199
200
        self.assertEqual('path/to/foo',
200
 
            dirname('path/to/foo/', exclude_trailing_slash=False))
 
201
                         dirname('path/to/foo/', exclude_trailing_slash=False))
201
202
        self.assertEqual('path/..', dirname('path/../foo'))
202
203
        self.assertEqual('../path', dirname('../path/foo'))
203
 
    
 
204
 
204
205
    def test_is_url(self):
205
206
        self.assertTrue(urlutils.is_url('http://foo/bar'))
206
207
        self.assertTrue(urlutils.is_url('bzr+ssh://foo/bar'))
221
222
            self.assertEqual(expected, joined)
222
223
 
223
224
        # Test relative path joining
224
 
        test('foo', 'foo') # relative fragment with nothing is preserved.
 
225
        test('foo', 'foo')  # relative fragment with nothing is preserved.
225
226
        test('foo/bar', 'foo', 'bar')
226
227
        test('http://foo/bar', 'http://foo', 'bar')
227
228
        test('http://foo/bar', 'http://foo', '.', 'bar')
233
234
        test('lp:foo/bar/baz', 'lp:foo', 'bar/baz')
234
235
 
235
236
        # Absolute paths
236
 
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
 
237
        test('http://foo', 'http://foo')  # abs url with nothing is preserved.
237
238
        test('http://bar', 'http://foo', 'http://bar')
238
239
        test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
239
240
        test('file:///bar', 'foo', 'file:///bar')
253
254
        # Invalid joinings
254
255
        # Cannot go above root
255
256
        # Implicitly at root:
256
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
257
 
                'http://foo', '../baz')
258
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
259
 
                'http://foo', '/..')
 
257
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.join,
 
258
                          'http://foo', '../baz')
 
259
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.join,
 
260
                          'http://foo', '/..')
260
261
        # Joining from a path explicitly under the root.
261
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
262
 
                'http://foo/a', '../../b')
 
262
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.join,
 
263
                          'http://foo/a', '../../b')
263
264
 
264
265
    def test_joinpath(self):
265
266
        def test(expected, *args):
290
291
 
291
292
        # Invalid joinings
292
293
        # Cannot go above root
293
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
294
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
295
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
 
294
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
 
295
                          '../baz')
 
296
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
 
297
                          '..')
 
298
        self.assertRaises(urlutils.InvalidURLJoin, urlutils.joinpath, '/',
 
299
                          '/..')
296
300
 
297
301
    def test_join_segment_parameters_raw(self):
298
302
        join_segment_parameters_raw = urlutils.join_segment_parameters_raw
299
 
        self.assertEquals("/somedir/path", 
300
 
            join_segment_parameters_raw("/somedir/path"))
301
 
        self.assertEquals("/somedir/path,rawdata", 
302
 
            join_segment_parameters_raw("/somedir/path", "rawdata"))
303
 
        self.assertRaises(InvalidURLJoin,
304
 
            join_segment_parameters_raw, "/somedir/path",
305
 
                "rawdata1,rawdata2,rawdata3")
306
 
        self.assertEquals("/somedir/path,bla,bar",
307
 
            join_segment_parameters_raw("/somedir/path", "bla", "bar"))
308
 
        self.assertEquals("/somedir,exist=some/path,bla,bar",
 
303
        self.assertEqual("/somedir/path",
 
304
                         join_segment_parameters_raw("/somedir/path"))
 
305
        self.assertEqual("/somedir/path,rawdata",
 
306
                         join_segment_parameters_raw(
 
307
                             "/somedir/path", "rawdata"))
 
308
        self.assertRaises(urlutils.InvalidURLJoin,
 
309
                          join_segment_parameters_raw, "/somedir/path",
 
310
                          "rawdata1,rawdata2,rawdata3")
 
311
        self.assertEqual("/somedir/path,bla,bar",
 
312
                         join_segment_parameters_raw(
 
313
                             "/somedir/path", "bla", "bar"))
 
314
        self.assertEqual(
 
315
            "/somedir,exist=some/path,bla,bar",
309
316
            join_segment_parameters_raw("/somedir,exist=some/path",
310
 
                "bla", "bar"))
311
 
        self.assertRaises(TypeError, join_segment_parameters_raw, 
312
 
            "/somepath", 42)
 
317
                                        "bla", "bar"))
 
318
        self.assertRaises(TypeError, join_segment_parameters_raw,
 
319
                          "/somepath", 42)
313
320
 
314
321
    def test_join_segment_parameters(self):
315
322
        join_segment_parameters = urlutils.join_segment_parameters
316
 
        self.assertEquals("/somedir/path", 
317
 
            join_segment_parameters("/somedir/path", {}))
318
 
        self.assertEquals("/somedir/path,key1=val1", 
 
323
        self.assertEqual("/somedir/path",
 
324
                         join_segment_parameters("/somedir/path", {}))
 
325
        self.assertEqual(
 
326
            "/somedir/path,key1=val1",
319
327
            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,
 
328
        self.assertRaises(urlutils.InvalidURLJoin,
 
329
                          join_segment_parameters, "/somedir/path",
 
330
                          {"branch": "brr,brr,brr"})
 
331
        self.assertRaises(
 
332
            urlutils.InvalidURLJoin,
324
333
            join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
325
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
326
 
            join_segment_parameters("/somedir/path", {
327
 
                "key1": "val1", "key2": "val2"}))
328
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
329
 
            join_segment_parameters("/somedir/path,key1=val1", {
330
 
                "key2": "val2"}))
331
 
        self.assertEquals("/somedir/path,key1=val2",
332
 
            join_segment_parameters("/somedir/path,key1=val1", {
333
 
                "key1": "val2"}))
334
 
        self.assertEquals("/somedir,exist=some/path,key1=val1",
335
 
            join_segment_parameters("/somedir,exist=some/path",
336
 
                {"key1": "val1"}))
337
 
        self.assertEquals("/,key1=val1,key2=val2",
 
334
        self.assertEqual("/somedir/path,key1=val1,key2=val2",
 
335
                         join_segment_parameters("/somedir/path", {
 
336
                             "key1": "val1", "key2": "val2"}))
 
337
        self.assertEqual("/somedir/path,key1=val1,key2=val2",
 
338
                         join_segment_parameters("/somedir/path,key1=val1", {
 
339
                             "key2": "val2"}))
 
340
        self.assertEqual("/somedir/path,key1=val2",
 
341
                         join_segment_parameters("/somedir/path,key1=val1", {
 
342
                             "key1": "val2"}))
 
343
        self.assertEqual("/somedir,exist=some/path,key1=val1",
 
344
                         join_segment_parameters("/somedir,exist=some/path",
 
345
                                                 {"key1": "val1"}))
 
346
        self.assertEqual(
 
347
            "/,key1=val1,key2=val2",
338
348
            join_segment_parameters("/,key1=val1", {"key2": "val2"}))
339
349
        self.assertRaises(TypeError,
340
 
            join_segment_parameters, "/,key1=val1", {"foo": 42})
 
350
                          join_segment_parameters, "/,key1=val1", {"foo": 42})
341
351
 
342
352
    def test_function_type(self):
343
353
        if sys.platform == 'win32':
344
354
            self.assertEqual(urlutils._win32_local_path_to_url,
345
 
                urlutils.local_path_to_url)
 
355
                             urlutils.local_path_to_url)
346
356
            self.assertEqual(urlutils._win32_local_path_from_url,
347
 
                urlutils.local_path_from_url)
 
357
                             urlutils.local_path_from_url)
348
358
        else:
349
359
            self.assertEqual(urlutils._posix_local_path_to_url,
350
 
                urlutils.local_path_to_url)
 
360
                             urlutils.local_path_to_url)
351
361
            self.assertEqual(urlutils._posix_local_path_from_url,
352
 
                urlutils.local_path_from_url)
 
362
                             urlutils.local_path_from_url)
353
363
 
354
364
    def test_posix_local_path_to_url(self):
355
365
        to_url = urlutils._posix_local_path_to_url
356
366
        self.assertEqual('file:///path/to/foo',
357
 
            to_url('/path/to/foo'))
 
367
                         to_url('/path/to/foo'))
358
368
 
359
369
        self.assertEqual('file:///path/to/foo%2Cbar',
360
 
            to_url('/path/to/foo,bar'))
 
370
                         to_url('/path/to/foo,bar'))
361
371
 
362
372
        try:
363
373
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
365
375
            raise TestSkipped("local encoding cannot handle unicode")
366
376
 
367
377
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
368
 
        self.assertFalse(isinstance(result, unicode))
 
378
        self.assertTrue(isinstance(result, str))
369
379
 
370
380
    def test_posix_local_path_from_url(self):
371
381
        from_url = urlutils._posix_local_path_from_url
372
382
        self.assertEqual('/path/to/foo',
373
 
            from_url('file:///path/to/foo'))
 
383
                         from_url('file:///path/to/foo'))
374
384
        self.assertEqual('/path/to/foo',
375
 
            from_url('file:///path/to/foo,branch=foo'))
376
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
377
 
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
378
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
379
 
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
380
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
 
385
                         from_url('file:///path/to/foo,branch=foo'))
 
386
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
 
387
                         from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
 
388
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
 
389
                         from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
 
390
        self.assertEqual(
 
391
            u'/path/to/r\xe4ksm\xf6rg\xe5s',
381
392
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
382
393
 
383
 
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
 
394
        self.assertRaises(urlutils.InvalidURL, from_url, '/path/to/foo')
384
395
        self.assertRaises(
385
 
            InvalidURL, from_url,
 
396
            urlutils.InvalidURL, from_url,
386
397
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
387
398
 
388
399
    def test_win32_local_path_to_url(self):
389
400
        to_url = urlutils._win32_local_path_to_url
390
401
        self.assertEqual('file:///C:/path/to/foo',
391
 
            to_url('C:/path/to/foo'))
 
402
                         to_url('C:/path/to/foo'))
392
403
        # BOGUS: on win32, ntpath.abspath will strip trailing
393
404
        #       whitespace, so this will always fail
394
405
        #       Though under linux, it fakes abspath support
396
407
        # self.assertEqual('file:///C:/path/to/foo%20',
397
408
        #     to_url('C:/path/to/foo '))
398
409
        self.assertEqual('file:///C:/path/to/f%20oo',
399
 
            to_url('C:/path/to/f oo'))
 
410
                         to_url('C:/path/to/f oo'))
400
411
 
401
412
        self.assertEqual('file:///', to_url('/'))
402
413
 
403
414
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
404
 
            to_url('C:/path/to/foo,bar'))
 
415
                         to_url('C:/path/to/foo,bar'))
405
416
        try:
406
417
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
407
418
        except UnicodeError:
408
419
            raise TestSkipped("local encoding cannot handle unicode")
409
420
 
410
 
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
411
 
        self.assertFalse(isinstance(result, unicode))
 
421
        self.assertEqual(
 
422
            'file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
423
        self.assertIsInstance(result, str)
412
424
 
413
425
    def test_win32_unc_path_to_url(self):
414
426
        self.requireFeature(features.win32_feature)
415
427
        to_url = urlutils._win32_local_path_to_url
416
428
        self.assertEqual('file://HOST/path',
417
 
            to_url(r'\\HOST\path'))
 
429
                         to_url(r'\\HOST\path'))
418
430
        self.assertEqual('file://HOST/path',
419
 
            to_url('//HOST/path'))
 
431
                         to_url('//HOST/path'))
420
432
 
421
433
        try:
422
434
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
423
435
        except UnicodeError:
424
436
            raise TestSkipped("local encoding cannot handle unicode")
425
437
 
426
 
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
427
 
        self.assertFalse(isinstance(result, unicode))
 
438
        self.assertEqual(
 
439
            'file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
 
440
        self.assertFalse(isinstance(result, str))
428
441
 
429
442
    def test_win32_local_path_from_url(self):
430
443
        from_url = urlutils._win32_local_path_from_url
431
444
        self.assertEqual('C:/path/to/foo',
432
 
            from_url('file:///C|/path/to/foo'))
433
 
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
 
445
                         from_url('file:///C|/path/to/foo'))
 
446
        self.assertEqual(
 
447
            u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
434
448
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
435
 
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
 
449
        self.assertEqual(
 
450
            u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
436
451
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
437
452
        self.assertEqual('/', from_url('file:///'))
438
453
        self.assertEqual('C:/path/to/foo',
439
 
            from_url('file:///C|/path/to/foo,branch=foo'))
 
454
                         from_url('file:///C|/path/to/foo,branch=foo'))
440
455
 
441
 
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
442
 
        self.assertRaises(InvalidURL, from_url, 'file:///c')
443
 
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
 
456
        self.assertRaises(urlutils.InvalidURL, from_url, 'file:///C:')
 
457
        self.assertRaises(urlutils.InvalidURL, from_url, 'file:///c')
 
458
        self.assertRaises(urlutils.InvalidURL, from_url, '/path/to/foo')
444
459
        # Not a valid _win32 url, no drive letter
445
 
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
 
460
        self.assertRaises(urlutils.InvalidURL, from_url, 'file:///path/to/foo')
446
461
 
447
462
    def test_win32_unc_path_from_url(self):
448
463
        from_url = urlutils._win32_local_path_from_url
449
464
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
450
465
        self.assertEqual('//HOST/path',
451
 
            from_url('file://HOST/path,branch=foo'))
 
466
                         from_url('file://HOST/path,branch=foo'))
452
467
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
453
468
        # we want to use only 2 slashes
454
469
        # 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')
 
470
        self.assertRaises(urlutils.InvalidURL, from_url, 'file:////HOST/path')
 
471
        self.assertRaises(urlutils.InvalidURL, from_url, 'file://///HOST/path')
 
472
        self.assertRaises(urlutils.InvalidURL, from_url,
 
473
                          'file://////HOST/path')
458
474
        # check for file://C:/ instead of file:///C:/
459
 
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
 
475
        self.assertRaises(urlutils.InvalidURL, from_url, 'file://C:/path')
460
476
 
461
477
    def test_win32_extract_drive_letter(self):
462
478
        extract = urlutils._win32_extract_drive_letter
463
479
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
464
 
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
465
 
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
 
480
        self.assertEqual(('file:///d|', '/path'),
 
481
                         extract('file://', '/d|/path'))
 
482
        self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/path')
466
483
        # Root drives without slash treated as invalid, see bug #841322
467
484
        self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
468
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:')
 
485
        self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:')
469
486
        # Invalid without drive separator or following forward slash
470
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C')
471
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:ool')
 
487
        self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C')
 
488
        self.assertRaises(urlutils.InvalidURL, extract, 'file://', '/C:ool')
472
489
 
473
490
    def test_split(self):
474
 
        # Test bzrlib.urlutils.split()
 
491
        # Test breezy.urlutils.split()
475
492
        split = urlutils.split
476
493
        if sys.platform == 'win32':
477
 
            self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
 
494
            self.assertRaises(urlutils.InvalidURL, split,
 
495
                              'file:///path/to/foo')
478
496
            self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
479
497
            self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
480
498
        else:
481
499
            self.assertEqual(('file:///', 'foo'), split('file:///foo'))
482
500
            self.assertEqual(('file:///', ''), split('file:///'))
483
501
 
484
 
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
485
 
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
486
 
        self.assertEqual(('http://host/path/to/foo', ''),
 
502
        self.assertEqual(('http://host/path/to', 'foo'),
 
503
                         split('http://host/path/to/foo'))
 
504
        self.assertEqual(('http://host/path/to', 'foo'),
 
505
                         split('http://host/path/to/foo/'))
 
506
        self.assertEqual(
 
507
            ('http://host/path/to/foo', ''),
487
508
            split('http://host/path/to/foo/', exclude_trailing_slash=False))
488
509
        self.assertEqual(('http://host/', 'path'), split('http://host/path'))
489
510
        self.assertEqual(('http://host/', ''), split('http://host/'))
490
511
        self.assertEqual(('http://host', ''), split('http://host'))
491
 
        self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
 
512
        self.assertEqual(('http:///nohost', 'path'),
 
513
                         split('http:///nohost/path'))
492
514
 
493
515
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
494
 
            split('random+scheme://user:pass@ahost:port/path'))
 
516
                         split('random+scheme://user:pass@ahost:port/path'))
495
517
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
496
 
            split('random+scheme://user:pass@ahost:port/path/'))
 
518
                         split('random+scheme://user:pass@ahost:port/path/'))
497
519
        self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
498
 
            split('random+scheme://user:pass@ahost:port/'))
 
520
                         split('random+scheme://user:pass@ahost:port/'))
499
521
 
500
522
        # relative paths
501
523
        self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
502
524
        self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
503
525
        self.assertEqual(('path/to/foo', ''),
504
 
            split('path/to/foo/', exclude_trailing_slash=False))
 
526
                         split('path/to/foo/', exclude_trailing_slash=False))
505
527
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
506
528
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
507
529
 
 
530
    def test_strip_segment_parameters(self):
 
531
        strip_segment_parameters = urlutils.strip_segment_parameters
 
532
        # Check relative references with absolute paths
 
533
        self.assertEqual("/some/path",
 
534
                         strip_segment_parameters("/some/path"))
 
535
        self.assertEqual("/some/path",
 
536
                         strip_segment_parameters("/some/path,tip"))
 
537
        self.assertEqual("/some,dir/path",
 
538
                         strip_segment_parameters("/some,dir/path,tip"))
 
539
        self.assertEqual(
 
540
            "/somedir/path",
 
541
            strip_segment_parameters("/somedir/path,heads%2Ftip"))
 
542
        self.assertEqual(
 
543
            "/somedir/path",
 
544
            strip_segment_parameters("/somedir/path,heads%2Ftip,bar"))
 
545
        # Check relative references with relative paths
 
546
        self.assertEqual("", strip_segment_parameters(",key1=val1"))
 
547
        self.assertEqual("foo/", strip_segment_parameters("foo/,key1=val1"))
 
548
        self.assertEqual("foo", strip_segment_parameters("foo,key1=val1"))
 
549
        self.assertEqual(
 
550
            "foo/base,la=bla/other/elements",
 
551
            strip_segment_parameters("foo/base,la=bla/other/elements"))
 
552
        self.assertEqual(
 
553
            "foo/base,la=bla/other/elements",
 
554
            strip_segment_parameters("foo/base,la=bla/other/elements,a=b"))
 
555
        # TODO: Check full URLs as well as relative references
 
556
 
508
557
    def test_split_segment_parameters_raw(self):
509
558
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
510
559
        # Check relative references with absolute paths
511
 
        self.assertEquals(("/some/path", []),
512
 
            split_segment_parameters_raw("/some/path"))
513
 
        self.assertEquals(("/some/path", ["tip"]),
514
 
            split_segment_parameters_raw("/some/path,tip"))
515
 
        self.assertEquals(("/some,dir/path", ["tip"]),
516
 
            split_segment_parameters_raw("/some,dir/path,tip"))
517
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
 
560
        self.assertEqual(("/some/path", []),
 
561
                         split_segment_parameters_raw("/some/path"))
 
562
        self.assertEqual(("/some/path", ["tip"]),
 
563
                         split_segment_parameters_raw("/some/path,tip"))
 
564
        self.assertEqual(("/some,dir/path", ["tip"]),
 
565
                         split_segment_parameters_raw("/some,dir/path,tip"))
 
566
        self.assertEqual(
 
567
            ("/somedir/path", ["heads%2Ftip"]),
518
568
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
519
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
 
569
        self.assertEqual(
 
570
            ("/somedir/path", ["heads%2Ftip", "bar"]),
520
571
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
521
572
        # Check relative references with relative paths
522
 
        self.assertEquals(("", ["key1=val1"]),
523
 
            split_segment_parameters_raw(",key1=val1"))
524
 
        self.assertEquals(("foo/", ["key1=val1"]),
525
 
            split_segment_parameters_raw("foo/,key1=val1"))
526
 
        self.assertEquals(("foo", ["key1=val1"]),
527
 
            split_segment_parameters_raw("foo,key1=val1"))
528
 
        self.assertEquals(("foo/base,la=bla/other/elements", []),
 
573
        self.assertEqual(("", ["key1=val1"]),
 
574
                         split_segment_parameters_raw(",key1=val1"))
 
575
        self.assertEqual(("foo/", ["key1=val1"]),
 
576
                         split_segment_parameters_raw("foo/,key1=val1"))
 
577
        self.assertEqual(("foo", ["key1=val1"]),
 
578
                         split_segment_parameters_raw("foo,key1=val1"))
 
579
        self.assertEqual(
 
580
            ("foo/base,la=bla/other/elements", []),
529
581
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
530
 
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
 
582
        self.assertEqual(
 
583
            ("foo/base,la=bla/other/elements", ["a=b"]),
531
584
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
532
585
        # TODO: Check full URLs as well as relative references
533
586
 
534
587
    def test_split_segment_parameters(self):
535
588
        split_segment_parameters = urlutils.split_segment_parameters
536
589
        # Check relative references with absolute paths
537
 
        self.assertEquals(("/some/path", {}),
538
 
            split_segment_parameters("/some/path"))
539
 
        self.assertEquals(("/some/path", {"branch": "tip"}),
540
 
            split_segment_parameters("/some/path,branch=tip"))
541
 
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
542
 
            split_segment_parameters("/some,dir/path,branch=tip"))
543
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
 
590
        self.assertEqual(("/some/path", {}),
 
591
                         split_segment_parameters("/some/path"))
 
592
        self.assertEqual(("/some/path", {"branch": "tip"}),
 
593
                         split_segment_parameters("/some/path,branch=tip"))
 
594
        self.assertEqual(("/some,dir/path", {"branch": "tip"}),
 
595
                         split_segment_parameters("/some,dir/path,branch=tip"))
 
596
        self.assertEqual(
 
597
            ("/somedir/path", {"ref": "heads%2Ftip"}),
544
598
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
545
 
        self.assertEquals(("/somedir/path",
546
 
            {"ref": "heads%2Ftip", "key1": "val1"}),
547
 
            split_segment_parameters(
548
 
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
549
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
 
599
        self.assertEqual(("/somedir/path",
 
600
                          {"ref": "heads%2Ftip", "key1": "val1"}),
 
601
                         split_segment_parameters(
 
602
            "/somedir/path,ref=heads%2Ftip,key1=val1"))
 
603
        self.assertEqual(
 
604
            ("/somedir/path", {"ref": "heads%2F=tip"}),
550
605
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
551
606
        # Check relative references with relative paths
552
 
        self.assertEquals(("", {"key1": "val1"}),
553
 
            split_segment_parameters(",key1=val1"))
554
 
        self.assertEquals(("foo/", {"key1": "val1"}),
555
 
            split_segment_parameters("foo/,key1=val1"))
556
 
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
 
607
        self.assertEqual(("", {"key1": "val1"}),
 
608
                         split_segment_parameters(",key1=val1"))
 
609
        self.assertEqual(("foo/", {"key1": "val1"}),
 
610
                         split_segment_parameters("foo/,key1=val1"))
 
611
        self.assertEqual(
 
612
            ("foo/base,key1=val1/other/elements", {}),
557
613
            split_segment_parameters("foo/base,key1=val1/other/elements"))
558
 
        self.assertEquals(("foo/base,key1=val1/other/elements",
559
 
            {"key2": "val2"}), split_segment_parameters(
560
 
                "foo/base,key1=val1/other/elements,key2=val2"))
 
614
        self.assertEqual(("foo/base,key1=val1/other/elements",
 
615
                          {"key2": "val2"}), split_segment_parameters(
 
616
            "foo/base,key1=val1/other/elements,key2=val2"))
 
617
        self.assertRaises(
 
618
            urlutils.InvalidURL, split_segment_parameters,
 
619
            "foo/base,key1")
561
620
        # TODO: Check full URLs as well as relative references
562
621
 
563
622
    def test_win32_strip_local_trailing_slash(self):
591
650
        self.assertEqual('file://', sts('file://'))
592
651
 
593
652
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
594
 
            sts('random+scheme://user:pass@ahost:port/path'))
 
653
                         sts('random+scheme://user:pass@ahost:port/path'))
595
654
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
596
 
            sts('random+scheme://user:pass@ahost:port/path/'))
 
655
                         sts('random+scheme://user:pass@ahost:port/path/'))
597
656
        self.assertEqual('random+scheme://user:pass@ahost:port/',
598
 
            sts('random+scheme://user:pass@ahost:port/'))
 
657
                         sts('random+scheme://user:pass@ahost:port/'))
599
658
 
600
659
        # Make sure relative paths work too
601
660
        self.assertEqual('path/to/foo', sts('path/to/foo'))
607
666
        # Test that URLs are converted to nice unicode strings for display
608
667
        def test(expected, url, encoding='utf-8'):
609
668
            disp_url = urlutils.unescape_for_display(url, encoding=encoding)
610
 
            self.assertIsInstance(disp_url, unicode)
 
669
            self.assertIsInstance(disp_url, str)
611
670
            self.assertEqual(expected, disp_url)
612
671
 
613
672
        test('http://foo', 'http://foo')
647
706
    def test_escape(self):
648
707
        self.assertEqual('%25', urlutils.escape('%'))
649
708
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
650
 
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
 
709
        self.assertIsInstance(urlutils.escape(u'\xe5'), str)
651
710
 
652
711
    def test_escape_tildes(self):
653
712
        self.assertEqual('~foo', urlutils.escape('~foo'))
656
715
        self.assertEqual('%', urlutils.unescape('%25'))
657
716
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
658
717
 
659
 
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
660
 
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
661
 
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
 
718
        self.assertRaises((TypeError, urlutils.InvalidURL),
 
719
                          urlutils.unescape, b'\xe5')
 
720
        self.assertEqual('\xe5', urlutils.unescape('%C3%A5'))
662
721
 
663
722
    def test_escape_unescape(self):
664
723
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
671
730
 
672
731
        test('a', 'http://host/', 'http://host/a')
673
732
        test('http://entirely/different', 'sftp://host/branch',
674
 
                    'http://entirely/different')
 
733
             'http://entirely/different')
675
734
        test('../person/feature', 'http://host/branch/mainline',
676
 
                    'http://host/branch/person/feature')
 
735
             'http://host/branch/person/feature')
677
736
        test('..', 'http://host/branch', 'http://host/')
678
 
        test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
 
737
        test('http://host2/branch', 'http://host1/branch',
 
738
             'http://host2/branch')
679
739
        test('.', 'http://host1/branch', 'http://host1/branch')
680
740
        test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
681
 
                    'file:///home/jelmer/branch/2b')
 
741
             'file:///home/jelmer/branch/2b')
682
742
        test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
683
 
                    'sftp://host/home/jelmer/branch/2b')
 
743
             'sftp://host/home/jelmer/branch/2b')
684
744
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
685
 
                    'http://host/home/jelmer/branch/feature/%2b')
 
745
             'http://host/home/jelmer/branch/feature/%2b')
686
746
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
687
 
                    'http://host/home/jelmer/branch/feature/2b')
 
747
             'http://host/home/jelmer/branch/feature/2b')
688
748
        # relative_url should preserve a trailing slash
689
749
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
690
 
                    'http://host/home/jelmer/branch/feature/2b/')
 
750
             'http://host/home/jelmer/branch/feature/2b/')
691
751
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
692
 
                    'http://host/home/jelmer/branch/feature/2b/')
 
752
             'http://host/home/jelmer/branch/feature/2b/')
693
753
 
694
754
        # TODO: treat http://host as http://host/
695
755
        #       relative_url is typically called from a branch.base or
696
756
        #       transport.base which always ends with a /
697
 
        #test('a', 'http://host', 'http://host/a')
 
757
        # test('a', 'http://host', 'http://host/a')
698
758
        test('http://host/a', 'http://host', 'http://host/a')
699
 
        #test('.', 'http://host', 'http://host/')
 
759
        # test('.', 'http://host', 'http://host/')
700
760
        test('http://host/', 'http://host', 'http://host/')
701
 
        #test('.', 'http://host/', 'http://host')
 
761
        # test('.', 'http://host/', 'http://host')
702
762
        test('http://host', 'http://host/', 'http://host')
703
763
 
704
764
        # On Windows file:///C:/path/to and file:///D:/other/path
706
766
        if sys.platform == 'win32':
707
767
            # on the same drive
708
768
            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')
 
769
                 'file:///C:/path/to', 'file:///C:/other/path')
 
770
            # ~next two tests is failed, i.e. urlutils.relative_url expects
 
771
            # ~to see normalized file URLs?
 
772
            # ~test('../../other/path',
 
773
            # ~    'file:///C:/path/to', 'file:///c:/other/path')
 
774
            # ~test('../../other/path',
 
775
            # ~    'file:///C:/path/to', 'file:///C|/other/path')
716
776
 
717
777
            # check UNC paths too
718
778
            test('../../other/path',
719
 
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
 
779
                 'file://HOST/base/path/to', 'file://HOST/base/other/path')
720
780
            # on different drives
721
781
            test('file:///D:/other/path',
722
 
                'file:///C:/path/to', 'file:///D:/other/path')
 
782
                 'file:///C:/path/to', 'file:///D:/other/path')
723
783
            # TODO: strictly saying in UNC path //HOST/base is full analog
724
784
            # of drive letter for hard disk, and this situation is also
725
785
            # should be exception from rules. [bialix 20071221]
737
797
        self.assertEndsWith(url, '/mytest')
738
798
 
739
799
    def test_non_ascii(self):
740
 
        if win32utils.winver == 'Windows 98':
741
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
742
 
 
743
800
        try:
744
801
            os.mkdir(u'dod\xe9')
745
802
        except UnicodeError:
785
842
        self.assertEqual('/foo', result)
786
843
 
787
844
    def test_different_ports(self):
788
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
845
        e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
789
846
                              'foo', 'http://bar:80', 'http://bar:81')
790
847
        self.assertEqual(str(e), "URLs differ by more than path:"
791
848
                         " 'http://bar:80' and 'http://bar:81'")
792
849
 
793
850
    def test_different_hosts(self):
794
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
851
        e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
795
852
                              'foo', 'http://bar', 'http://baz')
796
853
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
797
854
                         " and 'http://baz'")
798
855
 
799
856
    def test_different_protocol(self):
800
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
 
857
        e = self.assertRaises(urlutils.InvalidRebaseURLs, urlutils.rebase_url,
801
858
                              'foo', 'http://bar', 'ftp://bar')
802
859
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
803
860
                         " and 'ftp://bar'")
804
861
 
805
862
    def test_rebase_success(self):
806
863
        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/'))
 
864
                                                       'http://baz/qux'))
 
865
        self.assertEqual(
 
866
            'qux/bar',
 
867
            urlutils.rebase_url('bar', 'http://baz/qux', 'http://baz/'))
 
868
        self.assertEqual(
 
869
            '.', urlutils.rebase_url('foo', 'http://bar/', 'http://bar/foo/'))
 
870
        self.assertEqual(
 
871
            'qux/bar',
 
872
            urlutils.rebase_url('../bar', 'http://baz/qux/foo', 'http://baz/'))
814
873
 
815
874
    def test_determine_relative_path(self):
816
875
        self.assertEqual('../../baz/bar',
817
876
                         urlutils.determine_relative_path(
818
 
                         '/qux/quxx', '/baz/bar'))
 
877
                             '/qux/quxx', '/baz/bar'))
819
878
        self.assertEqual('..',
820
879
                         urlutils.determine_relative_path(
821
 
                         '/bar/baz', '/bar'))
 
880
                             '/bar/baz', '/bar'))
822
881
        self.assertEqual('baz',
823
882
                         urlutils.determine_relative_path(
824
 
                         '/bar', '/bar/baz'))
 
883
                             '/bar', '/bar/baz'))
825
884
        self.assertEqual('.', urlutils.determine_relative_path(
826
885
                         '/bar', '/bar'))
827
886
 
830
889
 
831
890
    def test_parse_simple(self):
832
891
        parsed = urlutils.parse_url('http://example.com:80/one')
833
 
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
834
 
            parsed)
 
892
        self.assertEqual(('http', None, None, 'example.com', 80, '/one'),
 
893
                         parsed)
835
894
 
836
895
    def test_ipv6(self):
837
896
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
838
 
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
839
 
            parsed)
 
897
        self.assertEqual(('http', None, None, '1:2:3::40', None, '/one'),
 
898
                         parsed)
840
899
 
841
900
    def test_ipv6_port(self):
842
901
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
843
 
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
844
 
            parsed)
 
902
        self.assertEqual(('http', None, None, '1:2:3::40', 80, '/one'),
 
903
                         parsed)
845
904
 
846
905
 
847
906
class TestURL(TestCase):
848
907
 
849
908
    def test_parse_simple(self):
850
909
        parsed = urlutils.URL.from_string('http://example.com:80/one')
851
 
        self.assertEquals('http', parsed.scheme)
 
910
        self.assertEqual('http', parsed.scheme)
852
911
        self.assertIs(None, parsed.user)
853
912
        self.assertIs(None, parsed.password)
854
 
        self.assertEquals('example.com', parsed.host)
855
 
        self.assertEquals(80, parsed.port)
856
 
        self.assertEquals('/one', parsed.path)
 
913
        self.assertEqual('example.com', parsed.host)
 
914
        self.assertEqual(80, parsed.port)
 
915
        self.assertEqual('/one', parsed.path)
857
916
 
858
917
    def test_ipv6(self):
859
918
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
860
 
        self.assertEquals('http', parsed.scheme)
 
919
        self.assertEqual('http', parsed.scheme)
861
920
        self.assertIs(None, parsed.port)
862
921
        self.assertIs(None, parsed.user)
863
922
        self.assertIs(None, parsed.password)
864
 
        self.assertEquals('1:2:3::40', parsed.host)
865
 
        self.assertEquals('/one', parsed.path)
 
923
        self.assertEqual('1:2:3::40', parsed.host)
 
924
        self.assertEqual('/one', parsed.path)
866
925
 
867
926
    def test_ipv6_port(self):
868
927
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
869
 
        self.assertEquals('http', parsed.scheme)
870
 
        self.assertEquals('1:2:3::40', parsed.host)
 
928
        self.assertEqual('http', parsed.scheme)
 
929
        self.assertEqual('1:2:3::40', parsed.host)
871
930
        self.assertIs(None, parsed.user)
872
931
        self.assertIs(None, parsed.password)
873
 
        self.assertEquals(80, parsed.port)
874
 
        self.assertEquals('/one', parsed.path)
 
932
        self.assertEqual(80, parsed.port)
 
933
        self.assertEqual('/one', parsed.path)
875
934
 
876
935
    def test_quoted(self):
877
936
        parsed = urlutils.URL.from_string(
878
937
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
879
 
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
880
 
        self.assertEquals(parsed.host, 'exAmple.com')
881
 
        self.assertEquals(parsed.port, 2222)
882
 
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
883
 
        self.assertEquals(parsed.user, 'robey')
884
 
        self.assertEquals(parsed.quoted_password, 'h%40t')
885
 
        self.assertEquals(parsed.password, 'h@t')
886
 
        self.assertEquals(parsed.path, '/path')
 
938
        self.assertEqual(parsed.quoted_host, 'ex%41mple.com')
 
939
        self.assertEqual(parsed.host, 'exAmple.com')
 
940
        self.assertEqual(parsed.port, 2222)
 
941
        self.assertEqual(parsed.quoted_user, 'ro%62ey')
 
942
        self.assertEqual(parsed.user, 'robey')
 
943
        self.assertEqual(parsed.quoted_password, 'h%40t')
 
944
        self.assertEqual(parsed.password, 'h@t')
 
945
        self.assertEqual(parsed.path, '/path')
887
946
 
888
947
    def test_eq(self):
889
948
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
890
949
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
891
 
        self.assertEquals(parsed1, parsed2)
892
 
        self.assertEquals(parsed1, parsed1)
 
950
        self.assertEqual(parsed1, parsed2)
 
951
        self.assertEqual(parsed1, parsed1)
893
952
        parsed2.path = '/two'
894
 
        self.assertNotEquals(parsed1, parsed2)
 
953
        self.assertNotEqual(parsed1, parsed2)
895
954
 
896
955
    def test_repr(self):
897
956
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
898
 
        self.assertEquals(
 
957
        self.assertEqual(
899
958
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
900
959
            repr(parsed))
901
960
 
902
961
    def test_str(self):
903
962
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
904
 
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
 
963
        self.assertEqual('http://[1:2:3::40]:80/one', str(parsed))
905
964
 
906
965
    def test__combine_paths(self):
907
966
        combine = urlutils.URL._combine_paths
917
976
    def test_clone(self):
918
977
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
919
978
        url1 = url.clone("two")
920
 
        self.assertEquals("/one/two", url1.path)
 
979
        self.assertEqual("/one/two", url1.path)
921
980
        url2 = url.clone("/two")
922
 
        self.assertEquals("/two", url2.path)
 
981
        self.assertEqual("/two", url2.path)
923
982
        url3 = url.clone()
924
983
        self.assertIsNot(url, url3)
925
 
        self.assertEquals(url, url3)
 
984
        self.assertEqual(url, url3)
 
985
 
 
986
    def test_parse_empty_port(self):
 
987
        parsed = urlutils.URL.from_string('http://example.com:/one')
 
988
        self.assertEqual('http', parsed.scheme)
 
989
        self.assertIs(None, parsed.user)
 
990
        self.assertIs(None, parsed.password)
 
991
        self.assertEqual('example.com', parsed.host)
 
992
        self.assertIs(None, parsed.port)
 
993
        self.assertEqual('/one', parsed.path)
926
994
 
927
995
 
928
996
class TestFileRelpath(TestCase):
932
1000
 
933
1001
    def _with_posix_paths(self):
934
1002
        self.overrideAttr(urlutils, "local_path_from_url",
935
 
            urlutils._posix_local_path_from_url)
 
1003
                          urlutils._posix_local_path_from_url)
936
1004
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH", len("file:///"))
937
1005
        self.overrideAttr(osutils, "normpath", osutils._posix_normpath)
938
1006
        self.overrideAttr(osutils, "abspath", osutils._posix_abspath)
943
1011
 
944
1012
    def _with_win32_paths(self):
945
1013
        self.overrideAttr(urlutils, "local_path_from_url",
946
 
            urlutils._win32_local_path_from_url)
 
1014
                          urlutils._win32_local_path_from_url)
947
1015
        self.overrideAttr(urlutils, "MIN_ABS_FILEURL_LENGTH",
948
 
            urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
 
1016
                          urlutils.WIN32_MIN_ABS_FILEURL_LENGTH)
949
1017
        self.overrideAttr(osutils, "abspath", osutils._win32_abspath)
950
1018
        self.overrideAttr(osutils, "normpath", osutils._win32_normpath)
951
1019
        self.overrideAttr(osutils, "pathjoin", osutils._win32_pathjoin)
954
1022
 
955
1023
    def test_same_url_posix(self):
956
1024
        self._with_posix_paths()
957
 
        self.assertEquals("",
958
 
            urlutils.file_relpath("file:///a", "file:///a"))
959
 
        self.assertEquals("",
960
 
            urlutils.file_relpath("file:///a", "file:///a/"))
961
 
        self.assertEquals("",
962
 
            urlutils.file_relpath("file:///a/", "file:///a"))
 
1025
        self.assertEqual("",
 
1026
                         urlutils.file_relpath("file:///a", "file:///a"))
 
1027
        self.assertEqual("",
 
1028
                         urlutils.file_relpath("file:///a", "file:///a/"))
 
1029
        self.assertEqual("",
 
1030
                         urlutils.file_relpath("file:///a/", "file:///a"))
963
1031
 
964
1032
    def test_same_url_win32(self):
965
1033
        self._with_win32_paths()
966
 
        self.assertEquals("",
967
 
            urlutils.file_relpath("file:///A:/", "file:///A:/"))
968
 
        self.assertEquals("",
969
 
            urlutils.file_relpath("file:///A|/", "file:///A:/"))
970
 
        self.assertEquals("",
971
 
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
972
 
        self.assertEquals("",
973
 
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
974
 
        self.assertEquals("",
975
 
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
 
1034
        self.assertEqual("",
 
1035
                         urlutils.file_relpath("file:///A:/", "file:///A:/"))
 
1036
        self.assertEqual("",
 
1037
                         urlutils.file_relpath("file:///A|/", "file:///A:/"))
 
1038
        self.assertEqual(
 
1039
            "", urlutils.file_relpath("file:///A:/b/", "file:///A:/b/"))
 
1040
        self.assertEqual(
 
1041
            "", urlutils.file_relpath("file:///A:/b", "file:///A:/b/"))
 
1042
        self.assertEqual(
 
1043
            "", urlutils.file_relpath("file:///A:/b/", "file:///A:/b"))
976
1044
 
977
1045
    def test_child_posix(self):
978
1046
        self._with_posix_paths()
979
 
        self.assertEquals("b",
980
 
            urlutils.file_relpath("file:///a", "file:///a/b"))
981
 
        self.assertEquals("b",
982
 
            urlutils.file_relpath("file:///a/", "file:///a/b"))
983
 
        self.assertEquals("b/c",
984
 
            urlutils.file_relpath("file:///a", "file:///a/b/c"))
 
1047
        self.assertEqual(
 
1048
            "b", urlutils.file_relpath("file:///a", "file:///a/b"))
 
1049
        self.assertEqual(
 
1050
            "b", urlutils.file_relpath("file:///a/", "file:///a/b"))
 
1051
        self.assertEqual(
 
1052
            "b/c", urlutils.file_relpath("file:///a", "file:///a/b/c"))
985
1053
 
986
1054
    def test_child_win32(self):
987
1055
        self._with_win32_paths()
988
 
        self.assertEquals("b",
989
 
            urlutils.file_relpath("file:///A:/", "file:///A:/b"))
990
 
        self.assertEquals("b",
991
 
            urlutils.file_relpath("file:///A|/", "file:///A:/b"))
992
 
        self.assertEquals("c",
993
 
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
994
 
        self.assertEquals("c",
995
 
            urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
996
 
        self.assertEquals("c/d",
997
 
            urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
 
1056
        self.assertEqual(
 
1057
            "b", urlutils.file_relpath("file:///A:/", "file:///A:/b"))
 
1058
        self.assertEqual(
 
1059
            "b", urlutils.file_relpath("file:///A|/", "file:///A:/b"))
 
1060
        self.assertEqual(
 
1061
            "c", urlutils.file_relpath("file:///A:/b", "file:///A:/b/c"))
 
1062
        self.assertEqual(
 
1063
            "c", urlutils.file_relpath("file:///A:/b/", "file:///A:/b/c"))
 
1064
        self.assertEqual(
 
1065
            "c/d", urlutils.file_relpath("file:///A:/b", "file:///A:/b/c/d"))
998
1066
 
999
1067
    def test_sibling_posix(self):
1000
1068
        self._with_posix_paths()
1001
 
        self.assertRaises(PathNotChild,
 
1069
        self.assertRaises(
 
1070
            PathNotChild,
1002
1071
            urlutils.file_relpath, "file:///a/b", "file:///a/c")
1003
 
        self.assertRaises(PathNotChild,
 
1072
        self.assertRaises(
 
1073
            PathNotChild,
1004
1074
            urlutils.file_relpath, "file:///a/b/", "file:///a/c")
1005
 
        self.assertRaises(PathNotChild,
 
1075
        self.assertRaises(
 
1076
            PathNotChild,
1006
1077
            urlutils.file_relpath, "file:///a/b/", "file:///a/c/")
1007
1078
 
1008
1079
    def test_sibling_win32(self):
1009
1080
        self._with_win32_paths()
1010
 
        self.assertRaises(PathNotChild,
 
1081
        self.assertRaises(
 
1082
            PathNotChild,
1011
1083
            urlutils.file_relpath, "file:///A:/b", "file:///A:/c")
1012
 
        self.assertRaises(PathNotChild,
 
1084
        self.assertRaises(
 
1085
            PathNotChild,
1013
1086
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c")
1014
 
        self.assertRaises(PathNotChild,
 
1087
        self.assertRaises(
 
1088
            PathNotChild,
1015
1089
            urlutils.file_relpath, "file:///A:/b/", "file:///A:/c/")
1016
1090
 
1017
1091
    def test_parent_posix(self):
1018
1092
        self._with_posix_paths()
1019
1093
        self.assertRaises(PathNotChild,
1020
 
            urlutils.file_relpath, "file:///a/b", "file:///a")
 
1094
                          urlutils.file_relpath, "file:///a/b", "file:///a")
1021
1095
        self.assertRaises(PathNotChild,
1022
 
            urlutils.file_relpath, "file:///a/b", "file:///a/")
 
1096
                          urlutils.file_relpath, "file:///a/b", "file:///a/")
1023
1097
 
1024
1098
    def test_parent_win32(self):
1025
1099
        self._with_win32_paths()
1026
 
        self.assertRaises(PathNotChild,
 
1100
        self.assertRaises(
 
1101
            PathNotChild,
1027
1102
            urlutils.file_relpath, "file:///A:/b", "file:///A:/")
1028
 
        self.assertRaises(PathNotChild,
 
1103
        self.assertRaises(
 
1104
            PathNotChild,
1029
1105
            urlutils.file_relpath, "file:///A:/b/c", "file:///A:/b")
1030
1106
 
1031
1107
 
1037
1113
        self.assertEqual('abc/def', urlutils.quote('abc/def', safe='/'))
1038
1114
 
1039
1115
    def test_quote_tildes(self):
1040
 
        self.assertEqual('%7Efoo', urlutils.quote('~foo'))
 
1116
        # Whether ~ is quoted by default depends on the python version
 
1117
        if sys.version_info[:2] >= (3, 7):
 
1118
            # https://docs.python.org/3/whatsnew/3.7.html#urllib-parse
 
1119
            self.assertEqual('~foo', urlutils.quote('~foo'))
 
1120
        else:
 
1121
            self.assertEqual('%7Efoo', urlutils.quote('~foo'))
1041
1122
        self.assertEqual('~foo', urlutils.quote('~foo', safe='/~'))
1042
1123
 
1043
1124
    def test_unquote(self):
1044
1125
        self.assertEqual('%', urlutils.unquote('%25'))
1045
 
        self.assertEqual('\xc3\xa5', urlutils.unquote('%C3%A5'))
 
1126
        self.assertEqual('\xe5', urlutils.unquote('%C3%A5'))
1046
1127
        self.assertEqual(u"\xe5", urlutils.unquote(u'\xe5'))
 
1128
 
 
1129
    def test_unquote_to_bytes(self):
 
1130
        self.assertEqual(b'%', urlutils.unquote_to_bytes('%25'))
 
1131
        self.assertEqual(b'\xc3\xa5', urlutils.unquote_to_bytes('%C3%A5'))