~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_urlutils.py

  • Committer: Aaron Bentley
  • Date: 2006-03-10 06:20:13 UTC
  • mto: (2027.1.2 revert-subpath-56549)
  • mto: This revision was merged to the branch mainline in revision 1647.
  • Revision ID: aaron.bentley@utoronto.ca-20060310062013-73726f82ca89344c
Conflict serialization working for WorkingTree3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
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
16
 
 
17
 
"""Tests for the urlutils wrapper."""
18
 
 
19
 
import os
20
 
import sys
21
 
 
22
 
from bzrlib import osutils, urlutils, win32utils
23
 
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
24
 
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
25
 
 
26
 
 
27
 
class TestUrlToPath(TestCase):
28
 
 
29
 
    def test_basename(self):
30
 
        # bzrlib.urlutils.basename
31
 
        # Test bzrlib.urlutils.split()
32
 
        basename = urlutils.basename
33
 
        if sys.platform == 'win32':
34
 
            self.assertRaises(InvalidURL, basename, 'file:///path/to/foo')
35
 
            self.assertEqual('foo', basename('file:///C|/foo'))
36
 
            self.assertEqual('foo', basename('file:///C:/foo'))
37
 
            self.assertEqual('', basename('file:///C:/'))
38
 
        else:
39
 
            self.assertEqual('foo', basename('file:///foo'))
40
 
            self.assertEqual('', basename('file:///'))
41
 
 
42
 
        self.assertEqual('foo', basename('http://host/path/to/foo'))
43
 
        self.assertEqual('foo', basename('http://host/path/to/foo/'))
44
 
        self.assertEqual('',
45
 
            basename('http://host/path/to/foo/', exclude_trailing_slash=False))
46
 
        self.assertEqual('path', basename('http://host/path'))
47
 
        self.assertEqual('', basename('http://host/'))
48
 
        self.assertEqual('', basename('http://host'))
49
 
        self.assertEqual('path', basename('http:///nohost/path'))
50
 
 
51
 
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path'))
52
 
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path/'))
53
 
        self.assertEqual('', basename('random+scheme://user:pass@ahost:port/'))
54
 
 
55
 
        # relative paths
56
 
        self.assertEqual('foo', basename('path/to/foo'))
57
 
        self.assertEqual('foo', basename('path/to/foo/'))
58
 
        self.assertEqual('', basename('path/to/foo/',
59
 
            exclude_trailing_slash=False))
60
 
        self.assertEqual('foo', basename('path/../foo'))
61
 
        self.assertEqual('foo', basename('../path/foo'))
62
 
 
63
 
    def test_normalize_url_files(self):
64
 
        # Test that local paths are properly normalized
65
 
        normalize_url = urlutils.normalize_url
66
 
 
67
 
        def norm_file(expected, path):
68
 
            url = normalize_url(path)
69
 
            self.assertStartsWith(url, 'file:///')
70
 
            if sys.platform == 'win32':
71
 
                url = url[len('file:///C:'):]
72
 
            else:
73
 
                url = url[len('file://'):]
74
 
 
75
 
            self.assertEndsWith(url, expected)
76
 
 
77
 
        norm_file('path/to/foo', 'path/to/foo')
78
 
        norm_file('/path/to/foo', '/path/to/foo')
79
 
        norm_file('path/to/foo', '../path/to/foo')
80
 
 
81
 
        # Local paths are assumed to *not* be escaped at all
82
 
        try:
83
 
            u'uni/\xb5'.encode(osutils.get_user_encoding())
84
 
        except UnicodeError:
85
 
            # locale cannot handle unicode
86
 
            pass
87
 
        else:
88
 
            norm_file('uni/%C2%B5', u'uni/\xb5')
89
 
 
90
 
        norm_file('uni/%25C2%25B5', u'uni/%C2%B5')
91
 
        norm_file('uni/%20b', u'uni/ b')
92
 
        # All the crazy characters get escaped in local paths => file:/// urls
93
 
        # The ' ' character must not be at the end, because on win32
94
 
        # it gets stripped off by ntpath.abspath
95
 
        norm_file('%27%20%3B/%3F%3A%40%26%3D%2B%24%2C%23', "' ;/?:@&=+$,#")
96
 
 
97
 
    def test_normalize_url_hybrid(self):
98
 
        # Anything with a scheme:// should be treated as a hybrid url
99
 
        # which changes what characters get escaped.
100
 
        normalize_url = urlutils.normalize_url
101
 
 
102
 
        eq = self.assertEqual
103
 
        eq('file:///foo/', normalize_url(u'file:///foo/'))
104
 
        eq('file:///foo/%20', normalize_url(u'file:///foo/ '))
105
 
        eq('file:///foo/%20', normalize_url(u'file:///foo/%20'))
106
 
        # Don't escape reserved characters
107
 
        eq('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$',
108
 
            normalize_url('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
109
 
        eq('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$',
110
 
            normalize_url('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
111
 
 
112
 
        # Escape unicode characters, but not already escaped chars
113
 
        eq('http://host/ab/%C2%B5/%C2%B5',
114
 
            normalize_url(u'http://host/ab/%C2%B5/\xb5'))
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
 
 
122
 
        # Normalize verifies URLs when they are not unicode
123
 
        # (indicating they did not come from the user)
124
 
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
125
 
        self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
126
 
 
127
 
    def test_url_scheme_re(self):
128
 
        # Test paths that may be URLs
129
 
        def test_one(url, scheme_and_path):
130
 
            """Assert that _url_scheme_re correctly matches
131
 
 
132
 
            :param scheme_and_path: The (scheme, path) that should be matched
133
 
                can be None, to indicate it should not match
134
 
            """
135
 
            m = urlutils._url_scheme_re.match(url)
136
 
            if scheme_and_path is None:
137
 
                self.assertEqual(None, m)
138
 
            else:
139
 
                self.assertEqual(scheme_and_path[0], m.group('scheme'))
140
 
                self.assertEqual(scheme_and_path[1], m.group('path'))
141
 
 
142
 
        # Local paths
143
 
        test_one('/path', None)
144
 
        test_one('C:/path', None)
145
 
        test_one('../path/to/foo', None)
146
 
        test_one(u'../path/to/fo\xe5', None)
147
 
 
148
 
        # Real URLS
149
 
        test_one('http://host/path/', ('http', 'host/path/'))
150
 
        test_one('sftp://host/path/to/foo', ('sftp', 'host/path/to/foo'))
151
 
        test_one('file:///usr/bin', ('file', '/usr/bin'))
152
 
        test_one('file:///C:/Windows', ('file', '/C:/Windows'))
153
 
        test_one('file:///C|/Windows', ('file', '/C|/Windows'))
154
 
        test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
155
 
 
156
 
        # Weird stuff
157
 
        # Can't have slashes or colons in the scheme
158
 
        test_one('/path/to/://foo', None)
159
 
        test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
160
 
        # Must have more than one character for scheme
161
 
        test_one('C://foo', None)
162
 
        test_one('ab://foo', ('ab', 'foo'))
163
 
 
164
 
    def test_dirname(self):
165
 
        # Test bzrlib.urlutils.dirname()
166
 
        dirname = urlutils.dirname
167
 
        if sys.platform == 'win32':
168
 
            self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
169
 
            self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
170
 
            self.assertEqual('file:///C|/', dirname('file:///C|/'))
171
 
        else:
172
 
            self.assertEqual('file:///', dirname('file:///foo'))
173
 
            self.assertEqual('file:///', dirname('file:///'))
174
 
 
175
 
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
176
 
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
177
 
        self.assertEqual('http://host/path/to/foo',
178
 
            dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
179
 
        self.assertEqual('http://host/', dirname('http://host/path'))
180
 
        self.assertEqual('http://host/', dirname('http://host/'))
181
 
        self.assertEqual('http://host', dirname('http://host'))
182
 
        self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
183
 
 
184
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
185
 
            dirname('random+scheme://user:pass@ahost:port/path'))
186
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
187
 
            dirname('random+scheme://user:pass@ahost:port/path/'))
188
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
189
 
            dirname('random+scheme://user:pass@ahost:port/'))
190
 
 
191
 
        # relative paths
192
 
        self.assertEqual('path/to', dirname('path/to/foo'))
193
 
        self.assertEqual('path/to', dirname('path/to/foo/'))
194
 
        self.assertEqual('path/to/foo',
195
 
            dirname('path/to/foo/', exclude_trailing_slash=False))
196
 
        self.assertEqual('path/..', dirname('path/../foo'))
197
 
        self.assertEqual('../path', dirname('../path/foo'))
198
 
    
199
 
    def test_is_url(self):
200
 
        self.assertTrue(urlutils.is_url('http://foo/bar'))
201
 
        self.assertTrue(urlutils.is_url('bzr+ssh://foo/bar'))
202
 
        self.assertTrue(urlutils.is_url('lp:foo/bar'))
203
 
        self.assertTrue(urlutils.is_url('file:///foo/bar'))
204
 
        self.assertFalse(urlutils.is_url(''))
205
 
        self.assertFalse(urlutils.is_url('foo'))
206
 
        self.assertFalse(urlutils.is_url('foo/bar'))
207
 
        self.assertFalse(urlutils.is_url('/foo'))
208
 
        self.assertFalse(urlutils.is_url('/foo/bar'))
209
 
        self.assertFalse(urlutils.is_url('C:/'))
210
 
        self.assertFalse(urlutils.is_url('C:/foo'))
211
 
        self.assertFalse(urlutils.is_url('C:/foo/bar'))
212
 
 
213
 
    def test_join(self):
214
 
        def test(expected, *args):
215
 
            joined = urlutils.join(*args)
216
 
            self.assertEqual(expected, joined)
217
 
 
218
 
        # Test relative path joining
219
 
        test('foo', 'foo') # relative fragment with nothing is preserved.
220
 
        test('foo/bar', 'foo', 'bar')
221
 
        test('http://foo/bar', 'http://foo', 'bar')
222
 
        test('http://foo/bar', 'http://foo', '.', 'bar')
223
 
        test('http://foo/baz', 'http://foo', 'bar', '../baz')
224
 
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
225
 
        test('http://foo/baz', 'http://foo', 'bar/../baz')
226
 
        test('http://foo/baz', 'http://foo/bar/', '../baz')
227
 
        test('lp:foo/bar', 'lp:foo', 'bar')
228
 
        test('lp:foo/bar/baz', 'lp:foo', 'bar/baz')
229
 
 
230
 
        # Absolute paths
231
 
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
232
 
        test('http://bar', 'http://foo', 'http://bar')
233
 
        test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
234
 
        test('file:///bar', 'foo', 'file:///bar')
235
 
        test('http://bar/', 'http://foo', 'http://bar/')
236
 
        test('http://bar/a', 'http://foo', 'http://bar/a')
237
 
        test('http://bar/a/', 'http://foo', 'http://bar/a/')
238
 
        test('lp:bar', 'http://foo', 'lp:bar')
239
 
        test('lp:bar', 'lp:foo', 'lp:bar')
240
 
        test('file:///stuff', 'lp:foo', 'file:///stuff')
241
 
 
242
 
        # From a base path
243
 
        test('file:///foo', 'file:///', 'foo')
244
 
        test('file:///bar/foo', 'file:///bar/', 'foo')
245
 
        test('http://host/foo', 'http://host/', 'foo')
246
 
        test('http://host/', 'http://host', '')
247
 
 
248
 
        # Invalid joinings
249
 
        # Cannot go above root
250
 
        # Implicitly at root:
251
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
252
 
                'http://foo', '../baz')
253
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
254
 
                'http://foo', '/..')
255
 
        # Joining from a path explicitly under the root.
256
 
        self.assertRaises(InvalidURLJoin, urlutils.join,
257
 
                'http://foo/a', '../../b')
258
 
 
259
 
    def test_joinpath(self):
260
 
        def test(expected, *args):
261
 
            joined = urlutils.joinpath(*args)
262
 
            self.assertEqual(expected, joined)
263
 
 
264
 
        # Test a single element
265
 
        test('foo', 'foo')
266
 
 
267
 
        # Test relative path joining
268
 
        test('foo/bar', 'foo', 'bar')
269
 
        test('foo/bar', 'foo', '.', 'bar')
270
 
        test('foo/baz', 'foo', 'bar', '../baz')
271
 
        test('foo/bar/baz', 'foo', 'bar/baz')
272
 
        test('foo/baz', 'foo', 'bar/../baz')
273
 
 
274
 
        # Test joining to an absolute path
275
 
        test('/foo', '/foo')
276
 
        test('/foo', '/foo', '.')
277
 
        test('/foo/bar', '/foo', 'bar')
278
 
        test('/', '/foo', '..')
279
 
 
280
 
        # Test joining with an absolute path
281
 
        test('/bar', 'foo', '/bar')
282
 
 
283
 
        # Test joining to a path with a trailing slash
284
 
        test('foo/bar', 'foo/', 'bar')
285
 
 
286
 
        # Invalid joinings
287
 
        # Cannot go above root
288
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
289
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
290
 
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
291
 
 
292
 
    def test_join_segment_parameters_raw(self):
293
 
        join_segment_parameters_raw = urlutils.join_segment_parameters_raw
294
 
        self.assertEquals("/somedir/path", 
295
 
            join_segment_parameters_raw("/somedir/path"))
296
 
        self.assertEquals("/somedir/path,rawdata", 
297
 
            join_segment_parameters_raw("/somedir/path", "rawdata"))
298
 
        self.assertRaises(InvalidURLJoin,
299
 
            join_segment_parameters_raw, "/somedir/path",
300
 
                "rawdata1,rawdata2,rawdata3")
301
 
        self.assertEquals("/somedir/path,bla,bar",
302
 
            join_segment_parameters_raw("/somedir/path", "bla", "bar"))
303
 
        self.assertEquals("/somedir,exist=some/path,bla,bar",
304
 
            join_segment_parameters_raw("/somedir,exist=some/path",
305
 
                "bla", "bar"))
306
 
        self.assertRaises(TypeError, join_segment_parameters_raw, 
307
 
            "/somepath", 42)
308
 
 
309
 
    def test_join_segment_parameters(self):
310
 
        join_segment_parameters = urlutils.join_segment_parameters
311
 
        self.assertEquals("/somedir/path", 
312
 
            join_segment_parameters("/somedir/path", {}))
313
 
        self.assertEquals("/somedir/path,key1=val1", 
314
 
            join_segment_parameters("/somedir/path", {"key1": "val1"}))
315
 
        self.assertRaises(InvalidURLJoin,
316
 
            join_segment_parameters, "/somedir/path",
317
 
            {"branch": "brr,brr,brr"})
318
 
        self.assertRaises(InvalidURLJoin,
319
 
            join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
320
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
321
 
            join_segment_parameters("/somedir/path", {
322
 
                "key1": "val1", "key2": "val2"}))
323
 
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
324
 
            join_segment_parameters("/somedir/path,key1=val1", {
325
 
                "key2": "val2"}))
326
 
        self.assertEquals("/somedir/path,key1=val2",
327
 
            join_segment_parameters("/somedir/path,key1=val1", {
328
 
                "key1": "val2"}))
329
 
        self.assertEquals("/somedir,exist=some/path,key1=val1",
330
 
            join_segment_parameters("/somedir,exist=some/path",
331
 
                {"key1": "val1"}))
332
 
        self.assertEquals("/,key1=val1,key2=val2",
333
 
            join_segment_parameters("/,key1=val1", {"key2": "val2"}))
334
 
        self.assertRaises(TypeError,
335
 
            join_segment_parameters, "/,key1=val1", {"foo": 42})
336
 
 
337
 
    def test_function_type(self):
338
 
        if sys.platform == 'win32':
339
 
            self.assertEqual(urlutils._win32_local_path_to_url,
340
 
                urlutils.local_path_to_url)
341
 
            self.assertEqual(urlutils._win32_local_path_from_url,
342
 
                urlutils.local_path_from_url)
343
 
        else:
344
 
            self.assertEqual(urlutils._posix_local_path_to_url,
345
 
                urlutils.local_path_to_url)
346
 
            self.assertEqual(urlutils._posix_local_path_from_url,
347
 
                urlutils.local_path_from_url)
348
 
 
349
 
    def test_posix_local_path_to_url(self):
350
 
        to_url = urlutils._posix_local_path_to_url
351
 
        self.assertEqual('file:///path/to/foo',
352
 
            to_url('/path/to/foo'))
353
 
 
354
 
        self.assertEqual('file:///path/to/foo%2Cbar',
355
 
            to_url('/path/to/foo,bar'))
356
 
 
357
 
        try:
358
 
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
359
 
        except UnicodeError:
360
 
            raise TestSkipped("local encoding cannot handle unicode")
361
 
 
362
 
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
363
 
        self.assertFalse(isinstance(result, unicode))
364
 
 
365
 
    def test_posix_local_path_from_url(self):
366
 
        from_url = urlutils._posix_local_path_from_url
367
 
        self.assertEqual('/path/to/foo',
368
 
            from_url('file:///path/to/foo'))
369
 
        self.assertEqual('/path/to/foo',
370
 
            from_url('file:///path/to/foo,branch=foo'))
371
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
372
 
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
373
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
374
 
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
375
 
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
376
 
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
377
 
 
378
 
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
379
 
        self.assertRaises(
380
 
            InvalidURL, from_url,
381
 
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
382
 
 
383
 
    def test_win32_local_path_to_url(self):
384
 
        to_url = urlutils._win32_local_path_to_url
385
 
        self.assertEqual('file:///C:/path/to/foo',
386
 
            to_url('C:/path/to/foo'))
387
 
        # BOGUS: on win32, ntpath.abspath will strip trailing
388
 
        #       whitespace, so this will always fail
389
 
        #       Though under linux, it fakes abspath support
390
 
        #       and thus will succeed
391
 
        # self.assertEqual('file:///C:/path/to/foo%20',
392
 
        #     to_url('C:/path/to/foo '))
393
 
        self.assertEqual('file:///C:/path/to/f%20oo',
394
 
            to_url('C:/path/to/f oo'))
395
 
 
396
 
        self.assertEqual('file:///', to_url('/'))
397
 
 
398
 
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
399
 
            to_url('C:/path/to/foo,bar'))
400
 
        try:
401
 
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
402
 
        except UnicodeError:
403
 
            raise TestSkipped("local encoding cannot handle unicode")
404
 
 
405
 
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
406
 
        self.assertFalse(isinstance(result, unicode))
407
 
 
408
 
    def test_win32_unc_path_to_url(self):
409
 
        to_url = urlutils._win32_local_path_to_url
410
 
        self.assertEqual('file://HOST/path',
411
 
            to_url(r'\\HOST\path'))
412
 
        self.assertEqual('file://HOST/path',
413
 
            to_url('//HOST/path'))
414
 
 
415
 
        try:
416
 
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
417
 
        except UnicodeError:
418
 
            raise TestSkipped("local encoding cannot handle unicode")
419
 
 
420
 
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
421
 
        self.assertFalse(isinstance(result, unicode))
422
 
 
423
 
    def test_win32_local_path_from_url(self):
424
 
        from_url = urlutils._win32_local_path_from_url
425
 
        self.assertEqual('C:/path/to/foo',
426
 
            from_url('file:///C|/path/to/foo'))
427
 
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
428
 
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
429
 
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
430
 
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
431
 
        self.assertEqual('/', from_url('file:///'))
432
 
        self.assertEqual('C:/path/to/foo',
433
 
            from_url('file:///C|/path/to/foo,branch=foo'))
434
 
 
435
 
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
436
 
        self.assertRaises(InvalidURL, from_url, 'file:///c')
437
 
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
438
 
        # Not a valid _win32 url, no drive letter
439
 
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
440
 
 
441
 
    def test_win32_unc_path_from_url(self):
442
 
        from_url = urlutils._win32_local_path_from_url
443
 
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
444
 
        self.assertEqual('//HOST/path',
445
 
            from_url('file://HOST/path,branch=foo'))
446
 
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
447
 
        # we want to use only 2 slashes
448
 
        # Firefox understand only 5 slashes in URL, but it's ugly
449
 
        self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
450
 
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
451
 
        self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
452
 
        # check for file://C:/ instead of file:///C:/
453
 
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
454
 
 
455
 
    def test_win32_extract_drive_letter(self):
456
 
        extract = urlutils._win32_extract_drive_letter
457
 
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
458
 
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
459
 
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
460
 
        # Root drives without slash treated as invalid, see bug #841322
461
 
        self.assertEqual(('file:///C:', '/'), extract('file://', '/C:/'))
462
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:')
463
 
        # Invalid without drive separator or following forward slash
464
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C')
465
 
        self.assertRaises(InvalidURL, extract, 'file://', '/C:ool')
466
 
 
467
 
    def test_split(self):
468
 
        # Test bzrlib.urlutils.split()
469
 
        split = urlutils.split
470
 
        if sys.platform == 'win32':
471
 
            self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
472
 
            self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
473
 
            self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
474
 
        else:
475
 
            self.assertEqual(('file:///', 'foo'), split('file:///foo'))
476
 
            self.assertEqual(('file:///', ''), split('file:///'))
477
 
 
478
 
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
479
 
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
480
 
        self.assertEqual(('http://host/path/to/foo', ''),
481
 
            split('http://host/path/to/foo/', exclude_trailing_slash=False))
482
 
        self.assertEqual(('http://host/', 'path'), split('http://host/path'))
483
 
        self.assertEqual(('http://host/', ''), split('http://host/'))
484
 
        self.assertEqual(('http://host', ''), split('http://host'))
485
 
        self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
486
 
 
487
 
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
488
 
            split('random+scheme://user:pass@ahost:port/path'))
489
 
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
490
 
            split('random+scheme://user:pass@ahost:port/path/'))
491
 
        self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
492
 
            split('random+scheme://user:pass@ahost:port/'))
493
 
 
494
 
        # relative paths
495
 
        self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
496
 
        self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
497
 
        self.assertEqual(('path/to/foo', ''),
498
 
            split('path/to/foo/', exclude_trailing_slash=False))
499
 
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
500
 
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
501
 
 
502
 
    def test_split_segment_parameters_raw(self):
503
 
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
504
 
        self.assertEquals(("/some/path", []),
505
 
            split_segment_parameters_raw("/some/path"))
506
 
        self.assertEquals(("/some/path", ["tip"]),
507
 
            split_segment_parameters_raw("/some/path,tip"))
508
 
        self.assertEquals(("/some,dir/path", ["tip"]),
509
 
            split_segment_parameters_raw("/some,dir/path,tip"))
510
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
511
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
512
 
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
513
 
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
514
 
        self.assertEquals(("/", ["key1=val1"]),
515
 
            split_segment_parameters_raw(",key1=val1"))
516
 
        self.assertEquals(("foo/", ["key1=val1"]),
517
 
            split_segment_parameters_raw("foo/,key1=val1"))
518
 
        self.assertEquals(("/foo", ["key1=val1"]),
519
 
            split_segment_parameters_raw("foo,key1=val1"))
520
 
        self.assertEquals(("foo/base,la=bla/other/elements", []),
521
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
522
 
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
523
 
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
524
 
 
525
 
    def test_split_segment_parameters(self):
526
 
        split_segment_parameters = urlutils.split_segment_parameters
527
 
        self.assertEquals(("/some/path", {}),
528
 
            split_segment_parameters("/some/path"))
529
 
        self.assertEquals(("/some/path", {"branch": "tip"}),
530
 
            split_segment_parameters("/some/path,branch=tip"))
531
 
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
532
 
            split_segment_parameters("/some,dir/path,branch=tip"))
533
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
534
 
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
535
 
        self.assertEquals(("/somedir/path",
536
 
            {"ref": "heads%2Ftip", "key1": "val1"}),
537
 
            split_segment_parameters(
538
 
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
539
 
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
540
 
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
541
 
        self.assertEquals(("/", {"key1": "val1"}),
542
 
            split_segment_parameters(",key1=val1"))
543
 
        self.assertEquals(("foo/", {"key1": "val1"}),
544
 
            split_segment_parameters("foo/,key1=val1"))
545
 
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
546
 
            split_segment_parameters("foo/base,key1=val1/other/elements"))
547
 
        self.assertEquals(("foo/base,key1=val1/other/elements",
548
 
            {"key2": "val2"}), split_segment_parameters(
549
 
                "foo/base,key1=val1/other/elements,key2=val2"))
550
 
 
551
 
    def test_win32_strip_local_trailing_slash(self):
552
 
        strip = urlutils._win32_strip_local_trailing_slash
553
 
        self.assertEqual('file://', strip('file://'))
554
 
        self.assertEqual('file:///', strip('file:///'))
555
 
        self.assertEqual('file:///C', strip('file:///C'))
556
 
        self.assertEqual('file:///C:', strip('file:///C:'))
557
 
        self.assertEqual('file:///d|', strip('file:///d|'))
558
 
        self.assertEqual('file:///C:/', strip('file:///C:/'))
559
 
        self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
560
 
 
561
 
    def test_strip_trailing_slash(self):
562
 
        sts = urlutils.strip_trailing_slash
563
 
        if sys.platform == 'win32':
564
 
            self.assertEqual('file:///C|/', sts('file:///C|/'))
565
 
            self.assertEqual('file:///C:/foo', sts('file:///C:/foo'))
566
 
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
567
 
        else:
568
 
            self.assertEqual('file:///', sts('file:///'))
569
 
            self.assertEqual('file:///foo', sts('file:///foo'))
570
 
            self.assertEqual('file:///foo', sts('file:///foo/'))
571
 
 
572
 
        self.assertEqual('http://host/', sts('http://host/'))
573
 
        self.assertEqual('http://host/foo', sts('http://host/foo'))
574
 
        self.assertEqual('http://host/foo', sts('http://host/foo/'))
575
 
 
576
 
        # No need to fail just because the slash is missing
577
 
        self.assertEqual('http://host', sts('http://host'))
578
 
        # TODO: jam 20060502 Should this raise InvalidURL?
579
 
        self.assertEqual('file://', sts('file://'))
580
 
 
581
 
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
582
 
            sts('random+scheme://user:pass@ahost:port/path'))
583
 
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
584
 
            sts('random+scheme://user:pass@ahost:port/path/'))
585
 
        self.assertEqual('random+scheme://user:pass@ahost:port/',
586
 
            sts('random+scheme://user:pass@ahost:port/'))
587
 
 
588
 
        # Make sure relative paths work too
589
 
        self.assertEqual('path/to/foo', sts('path/to/foo'))
590
 
        self.assertEqual('path/to/foo', sts('path/to/foo/'))
591
 
        self.assertEqual('../to/foo', sts('../to/foo/'))
592
 
        self.assertEqual('path/../foo', sts('path/../foo/'))
593
 
 
594
 
    def test_unescape_for_display_utf8(self):
595
 
        # Test that URLs are converted to nice unicode strings for display
596
 
        def test(expected, url, encoding='utf-8'):
597
 
            disp_url = urlutils.unescape_for_display(url, encoding=encoding)
598
 
            self.assertIsInstance(disp_url, unicode)
599
 
            self.assertEqual(expected, disp_url)
600
 
 
601
 
        test('http://foo', 'http://foo')
602
 
        if sys.platform == 'win32':
603
 
            test('C:/foo/path', 'file:///C|/foo/path')
604
 
            test('C:/foo/path', 'file:///C:/foo/path')
605
 
        else:
606
 
            test('/foo/path', 'file:///foo/path')
607
 
 
608
 
        test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
609
 
        test(u'http://host/r\xe4ksm\xf6rg\xe5s',
610
 
             'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
611
 
 
612
 
        # Make sure special escaped characters stay escaped
613
 
        test(u'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23',
614
 
             'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23')
615
 
 
616
 
        # Can we handle sections that don't have utf-8 encoding?
617
 
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
618
 
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s')
619
 
 
620
 
        # Test encoding into output that can handle some characters
621
 
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
622
 
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
623
 
             encoding='iso-8859-1')
624
 
 
625
 
        # This one can be encoded into utf8
626
 
        test(u'http://host/\u062c\u0648\u062c\u0648',
627
 
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
628
 
             encoding='utf-8')
629
 
 
630
 
        # This can't be put into 8859-1 and so stays as escapes
631
 
        test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
632
 
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
633
 
             encoding='iso-8859-1')
634
 
 
635
 
    def test_escape(self):
636
 
        self.assertEqual('%25', urlutils.escape('%'))
637
 
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
638
 
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
639
 
 
640
 
    def test_escape_tildes(self):
641
 
        self.assertEqual('~foo', urlutils.escape('~foo'))
642
 
 
643
 
    def test_unescape(self):
644
 
        self.assertEqual('%', urlutils.unescape('%25'))
645
 
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
646
 
 
647
 
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
648
 
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
649
 
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
650
 
 
651
 
    def test_escape_unescape(self):
652
 
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
653
 
        self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
654
 
 
655
 
    def test_relative_url(self):
656
 
        def test(expected, base, other):
657
 
            result = urlutils.relative_url(base, other)
658
 
            self.assertEqual(expected, result)
659
 
 
660
 
        test('a', 'http://host/', 'http://host/a')
661
 
        test('http://entirely/different', 'sftp://host/branch',
662
 
                    'http://entirely/different')
663
 
        test('../person/feature', 'http://host/branch/mainline',
664
 
                    'http://host/branch/person/feature')
665
 
        test('..', 'http://host/branch', 'http://host/')
666
 
        test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
667
 
        test('.', 'http://host1/branch', 'http://host1/branch')
668
 
        test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
669
 
                    'file:///home/jelmer/branch/2b')
670
 
        test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
671
 
                    'sftp://host/home/jelmer/branch/2b')
672
 
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
673
 
                    'http://host/home/jelmer/branch/feature/%2b')
674
 
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
675
 
                    'http://host/home/jelmer/branch/feature/2b')
676
 
        # relative_url should preserve a trailing slash
677
 
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
678
 
                    'http://host/home/jelmer/branch/feature/2b/')
679
 
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
680
 
                    'http://host/home/jelmer/branch/feature/2b/')
681
 
 
682
 
        # TODO: treat http://host as http://host/
683
 
        #       relative_url is typically called from a branch.base or
684
 
        #       transport.base which always ends with a /
685
 
        #test('a', 'http://host', 'http://host/a')
686
 
        test('http://host/a', 'http://host', 'http://host/a')
687
 
        #test('.', 'http://host', 'http://host/')
688
 
        test('http://host/', 'http://host', 'http://host/')
689
 
        #test('.', 'http://host/', 'http://host')
690
 
        test('http://host', 'http://host/', 'http://host')
691
 
 
692
 
        # On Windows file:///C:/path/to and file:///D:/other/path
693
 
        # should not use relative url over the non-existent '/' directory.
694
 
        if sys.platform == 'win32':
695
 
            # on the same drive
696
 
            test('../../other/path',
697
 
                'file:///C:/path/to', 'file:///C:/other/path')
698
 
            #~next two tests is failed, i.e. urlutils.relative_url expects
699
 
            #~to see normalized file URLs?
700
 
            #~test('../../other/path',
701
 
            #~    'file:///C:/path/to', 'file:///c:/other/path')
702
 
            #~test('../../other/path',
703
 
            #~    'file:///C:/path/to', 'file:///C|/other/path')
704
 
 
705
 
            # check UNC paths too
706
 
            test('../../other/path',
707
 
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
708
 
            # on different drives
709
 
            test('file:///D:/other/path',
710
 
                'file:///C:/path/to', 'file:///D:/other/path')
711
 
            # TODO: strictly saying in UNC path //HOST/base is full analog
712
 
            # of drive letter for hard disk, and this situation is also
713
 
            # should be exception from rules. [bialix 20071221]
714
 
 
715
 
 
716
 
class TestCwdToURL(TestCaseInTempDir):
717
 
    """Test that local_path_to_url works base on the cwd"""
718
 
 
719
 
    def test_dot(self):
720
 
        # This test will fail if getcwd is not ascii
721
 
        os.mkdir('mytest')
722
 
        os.chdir('mytest')
723
 
 
724
 
        url = urlutils.local_path_to_url('.')
725
 
        self.assertEndsWith(url, '/mytest')
726
 
 
727
 
    def test_non_ascii(self):
728
 
        if win32utils.winver == 'Windows 98':
729
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
730
 
 
731
 
        try:
732
 
            os.mkdir(u'dod\xe9')
733
 
        except UnicodeError:
734
 
            raise TestSkipped('cannot create unicode directory')
735
 
 
736
 
        os.chdir(u'dod\xe9')
737
 
 
738
 
        # On Mac OSX this directory is actually:
739
 
        #   u'/dode\u0301' => '/dode\xcc\x81
740
 
        # but we should normalize it back to
741
 
        #   u'/dod\xe9' => '/dod\xc3\xa9'
742
 
        url = urlutils.local_path_to_url('.')
743
 
        self.assertEndsWith(url, '/dod%C3%A9')
744
 
 
745
 
 
746
 
class TestDeriveToLocation(TestCase):
747
 
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
748
 
 
749
 
    def test_to_locations_derived_from_paths(self):
750
 
        derive = urlutils.derive_to_location
751
 
        self.assertEqual("bar", derive("bar"))
752
 
        self.assertEqual("bar", derive("../bar"))
753
 
        self.assertEqual("bar", derive("/foo/bar"))
754
 
        self.assertEqual("bar", derive("c:/foo/bar"))
755
 
        self.assertEqual("bar", derive("c:bar"))
756
 
 
757
 
    def test_to_locations_derived_from_urls(self):
758
 
        derive = urlutils.derive_to_location
759
 
        self.assertEqual("bar", derive("http://foo/bar"))
760
 
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
761
 
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
762
 
 
763
 
 
764
 
class TestRebaseURL(TestCase):
765
 
    """Test the behavior of rebase_url."""
766
 
 
767
 
    def test_non_relative(self):
768
 
        result = urlutils.rebase_url('file://foo', 'file://foo',
769
 
                                     'file://foo/bar')
770
 
        self.assertEqual('file://foo', result)
771
 
        result = urlutils.rebase_url('/foo', 'file://foo',
772
 
                                     'file://foo/bar')
773
 
        self.assertEqual('/foo', result)
774
 
 
775
 
    def test_different_ports(self):
776
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
777
 
                              'foo', 'http://bar:80', 'http://bar:81')
778
 
        self.assertEqual(str(e), "URLs differ by more than path:"
779
 
                         " 'http://bar:80' and 'http://bar:81'")
780
 
 
781
 
    def test_different_hosts(self):
782
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
783
 
                              'foo', 'http://bar', 'http://baz')
784
 
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
785
 
                         " and 'http://baz'")
786
 
 
787
 
    def test_different_protocol(self):
788
 
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
789
 
                              'foo', 'http://bar', 'ftp://bar')
790
 
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
791
 
                         " and 'ftp://bar'")
792
 
 
793
 
    def test_rebase_success(self):
794
 
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
795
 
                         'http://baz/qux'))
796
 
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
797
 
                         'http://baz/qux', 'http://baz/'))
798
 
        self.assertEqual('.', urlutils.rebase_url('foo',
799
 
                         'http://bar/', 'http://bar/foo/'))
800
 
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
801
 
                         'http://baz/qux/foo', 'http://baz/'))
802
 
 
803
 
    def test_determine_relative_path(self):
804
 
        self.assertEqual('../../baz/bar',
805
 
                         urlutils.determine_relative_path(
806
 
                         '/qux/quxx', '/baz/bar'))
807
 
        self.assertEqual('..',
808
 
                         urlutils.determine_relative_path(
809
 
                         '/bar/baz', '/bar'))
810
 
        self.assertEqual('baz',
811
 
                         urlutils.determine_relative_path(
812
 
                         '/bar', '/bar/baz'))
813
 
        self.assertEqual('.', urlutils.determine_relative_path(
814
 
                         '/bar', '/bar'))
815
 
 
816
 
 
817
 
class TestParseURL(TestCase):
818
 
 
819
 
    def test_parse_simple(self):
820
 
        parsed = urlutils.parse_url('http://example.com:80/one')
821
 
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
822
 
            parsed)
823
 
 
824
 
    def test_ipv6(self):
825
 
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
826
 
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
827
 
            parsed)
828
 
 
829
 
    def test_ipv6_port(self):
830
 
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
831
 
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
832
 
            parsed)
833
 
 
834
 
 
835
 
class TestURL(TestCase):
836
 
 
837
 
    def test_parse_simple(self):
838
 
        parsed = urlutils.URL.from_string('http://example.com:80/one')
839
 
        self.assertEquals('http', parsed.scheme)
840
 
        self.assertIs(None, parsed.user)
841
 
        self.assertIs(None, parsed.password)
842
 
        self.assertEquals('example.com', parsed.host)
843
 
        self.assertEquals(80, parsed.port)
844
 
        self.assertEquals('/one', parsed.path)
845
 
 
846
 
    def test_ipv6(self):
847
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
848
 
        self.assertEquals('http', parsed.scheme)
849
 
        self.assertIs(None, parsed.port)
850
 
        self.assertIs(None, parsed.user)
851
 
        self.assertIs(None, parsed.password)
852
 
        self.assertEquals('1:2:3::40', parsed.host)
853
 
        self.assertEquals('/one', parsed.path)
854
 
 
855
 
    def test_ipv6_port(self):
856
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
857
 
        self.assertEquals('http', parsed.scheme)
858
 
        self.assertEquals('1:2:3::40', parsed.host)
859
 
        self.assertIs(None, parsed.user)
860
 
        self.assertIs(None, parsed.password)
861
 
        self.assertEquals(80, parsed.port)
862
 
        self.assertEquals('/one', parsed.path)
863
 
 
864
 
    def test_quoted(self):
865
 
        parsed = urlutils.URL.from_string(
866
 
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
867
 
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
868
 
        self.assertEquals(parsed.host, 'exAmple.com')
869
 
        self.assertEquals(parsed.port, 2222)
870
 
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
871
 
        self.assertEquals(parsed.user, 'robey')
872
 
        self.assertEquals(parsed.quoted_password, 'h%40t')
873
 
        self.assertEquals(parsed.password, 'h@t')
874
 
        self.assertEquals(parsed.path, '/path')
875
 
 
876
 
    def test_eq(self):
877
 
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
878
 
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
879
 
        self.assertEquals(parsed1, parsed2)
880
 
        self.assertEquals(parsed1, parsed1)
881
 
        parsed2.path = '/two'
882
 
        self.assertNotEquals(parsed1, parsed2)
883
 
 
884
 
    def test_repr(self):
885
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
886
 
        self.assertEquals(
887
 
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
888
 
            repr(parsed))
889
 
 
890
 
    def test_str(self):
891
 
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
892
 
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
893
 
 
894
 
    def test__combine_paths(self):
895
 
        combine = urlutils.URL._combine_paths
896
 
        self.assertEqual('/home/sarah/project/foo',
897
 
                         combine('/home/sarah', 'project/foo'))
898
 
        self.assertEqual('/etc',
899
 
                         combine('/home/sarah', '../../etc'))
900
 
        self.assertEqual('/etc',
901
 
                         combine('/home/sarah', '../../../etc'))
902
 
        self.assertEqual('/etc',
903
 
                         combine('/home/sarah', '/etc'))
904
 
 
905
 
    def test_clone(self):
906
 
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
907
 
        url1 = url.clone("two")
908
 
        self.assertEquals("/one/two", url1.path)
909
 
        url2 = url.clone("/two")
910
 
        self.assertEquals("/two", url2.path)
911
 
        url3 = url.clone()
912
 
        self.assertIsNot(url, url3)
913
 
        self.assertEquals(url, url3)