~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 Canonical Ltd
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
16
17
"""Tests for the urlutils wrapper."""
18
19
import os
20
import sys
21
2279.4.2 by Alexander Belchenko
Don't do normpath after abspath, because this function is called inside abspath
22
from bzrlib import osutils, urlutils, win32utils
3242.3.33 by Aaron Bentley
Handle relative URL stacking cleanly
23
from bzrlib.errors import InvalidURL, InvalidURLJoin, InvalidRebaseURLs
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
24
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
25
26
27
class TestUrlToPath(TestCase):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
28
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
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'))
1685.1.78 by Wouter van Heyst
more code cleanup
36
            self.assertEqual('foo', basename('file:///C:/foo'))
37
            self.assertEqual('', basename('file:///C:/'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
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
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
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
1685.1.53 by John Arbash Meinel
Updated normalize_url
75
            self.assertEndsWith(url, expected)
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
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
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
82
        try:
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
83
            u'uni/\xb5'.encode(osutils.get_user_encoding())
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
84
        except UnicodeError:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
85
            # locale cannot handle unicode
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
86
            pass
87
        else:
88
            norm_file('uni/%C2%B5', u'uni/\xb5')
89
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
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
1711.4.4 by John Arbash Meinel
Fix some broken tests because of stupid ntpath.abspath behavior
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', "' ;/?:@&=+$,#")
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
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
2208.4.1 by Andrew Bennetts
normalize_url should normalise escaping of unreserved characters, like '~'.
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
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
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/ ')
1685.1.50 by John Arbash Meinel
Added an re for handling scheme paths.
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)
5254.1.5 by Gordon Tyler
Fixes according to spiv's review.
159
        test_one('scheme:stuff://foo', ('scheme', 'stuff://foo'))
1685.1.50 by John Arbash Meinel
Added an re for handling scheme paths.
160
        # Must have more than one character for scheme
161
        test_one('C://foo', None)
162
        test_one('ab://foo', ('ab', 'foo'))
163
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
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'))
5254.2.1 by Gordon Tyler
Fixed how get_transport's convert_path_to_url tests whether a path is actually a URL.
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'))
5254.2.5 by Andrew Bennetts
Revert debugging change accidentally committed by Gordon Tyler.
211
        self.assertFalse(urlutils.is_url('C:/foo/bar'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
212
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
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
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
219
        test('foo', 'foo') # relative fragment with nothing is preserved.
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
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')
2018.5.93 by Andrew Bennetts
Fix another bug in urlutils.join.
226
        test('http://foo/baz', 'http://foo/bar/', '../baz')
5254.1.1 by Gordon Tyler
Added support to urlutils for URLs such as Launchpad's lp:foobar.
227
        test('lp:foo/bar', 'lp:foo', 'bar')
228
        test('lp:foo/bar/baz', 'lp:foo', 'bar/baz')
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
229
230
        # Absolute paths
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
231
        test('http://foo', 'http://foo') # abs url with nothing is preserved.
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
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')
2018.5.92 by Andrew Bennetts
Small bugfix to urlutils.join: join('anything', 'http://bar/a/') should not strip the trailing slash.
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/')
5254.1.1 by Gordon Tyler
Added support to urlutils for URLs such as Launchpad's lp:foobar.
238
        test('lp:bar', 'http://foo', 'lp:bar')
239
        test('lp:bar', 'lp:foo', 'lp:bar')
240
        test('file:///stuff', 'lp:foo', 'file:///stuff')
1711.2.49 by John Arbash Meinel
urlutils.join should work for root paths.
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', '')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
247
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
248
        # Invalid joinings
249
        # Cannot go above root
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
250
        # Implicitly at root:
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
251
        self.assertRaises(InvalidURLJoin, urlutils.join,
252
                'http://foo', '../baz')
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
253
        self.assertRaises(InvalidURLJoin, urlutils.join,
254
                'http://foo', '/..')
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
255
        # Joining from a path explicitly under the root.
256
        self.assertRaises(InvalidURLJoin, urlutils.join,
257
                'http://foo/a', '../../b')
2379.1.1 by Robert Collins
urlutils improvements from hpss.
258
2018.5.46 by Andrew Bennetts
Fix ChrootTransportDecorator's clone to pass less surprising offsets to the decorated transport's clone.
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')
2018.5.53 by Andrew Bennetts
Small fix to urlutils.joinpath that was causing a misbehaviour in
282
283
        # Test joining to a path with a trailing slash
284
        test('foo/bar', 'foo/', 'bar')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
285
2018.5.46 by Andrew Bennetts
Fix ChrootTransportDecorator's clone to pass less surprising offsets to the decorated transport's clone.
286
        # Invalid joinings
287
        # Cannot go above root
288
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
289
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
290
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '/..')
2018.5.46 by Andrew Bennetts
Fix ChrootTransportDecorator's clone to pass less surprising offsets to the decorated transport's clone.
291
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
292
    def test_join_segment_parameters_raw(self):
293
        join_segment_parameters_raw = urlutils.join_segment_parameters_raw
5163.2.2 by Jelmer Vernooij
Add bzrlib.urlutils.join_subsegments.
294
        self.assertEquals("/somedir/path", 
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
295
            join_segment_parameters_raw("/somedir/path"))
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
296
        self.assertEquals("/somedir/path,rawdata", 
297
            join_segment_parameters_raw("/somedir/path", "rawdata"))
5163.2.2 by Jelmer Vernooij
Add bzrlib.urlutils.join_subsegments.
298
        self.assertRaises(InvalidURLJoin,
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
299
            join_segment_parameters_raw, "/somedir/path",
300
                "rawdata1,rawdata2,rawdata3")
5163.2.2 by Jelmer Vernooij
Add bzrlib.urlutils.join_subsegments.
301
        self.assertEquals("/somedir/path,bla,bar",
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
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"))
5163.2.7 by Jelmer Vernooij
Add type checking.
306
        self.assertRaises(TypeError, join_segment_parameters_raw, 
307
            "/somepath", 42)
5163.2.2 by Jelmer Vernooij
Add bzrlib.urlutils.join_subsegments.
308
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
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", {}))
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
313
        self.assertEquals("/somedir/path,key1=val1", 
314
            join_segment_parameters("/somedir/path", {"key1": "val1"}))
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
315
        self.assertRaises(InvalidURLJoin,
316
            join_segment_parameters, "/somedir/path",
317
            {"branch": "brr,brr,brr"})
318
        self.assertRaises(InvalidURLJoin,
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
319
            join_segment_parameters, "/somedir/path", {"key1=val1": "val2"})
320
        self.assertEquals("/somedir/path,key1=val1,key2=val2",
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
321
            join_segment_parameters("/somedir/path", {
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
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",
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
330
            join_segment_parameters("/somedir,exist=some/path",
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
331
                {"key1": "val1"}))
332
        self.assertEquals("/,key1=val1,key2=val2",
333
            join_segment_parameters("/,key1=val1", {"key2": "val2"}))
5163.2.7 by Jelmer Vernooij
Add type checking.
334
        self.assertRaises(TypeError,
335
            join_segment_parameters, "/,key1=val1", {"foo": 42})
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
336
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
337
    def test_function_type(self):
338
        if sys.platform == 'win32':
339
            self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
340
            self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
341
        else:
342
            self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
343
            self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
344
345
    def test_posix_local_path_to_url(self):
346
        to_url = urlutils._posix_local_path_to_url
347
        self.assertEqual('file:///path/to/foo',
348
            to_url('/path/to/foo'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
349
350
        try:
351
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
352
        except UnicodeError:
353
            raise TestSkipped("local encoding cannot handle unicode")
354
355
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
3234.3.1 by Alexander Belchenko
ensure that local_path_to_url() always returns plain string, not unicode.
356
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
357
358
    def test_posix_local_path_from_url(self):
359
        from_url = urlutils._posix_local_path_from_url
360
        self.assertEqual('/path/to/foo',
361
            from_url('file:///path/to/foo'))
362
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
363
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
364
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
365
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
4828.1.1 by Michael Hudson
test and fix
366
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
367
            from_url('file://localhost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
368
369
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
4828.1.1 by Michael Hudson
test and fix
370
        self.assertRaises(
371
            InvalidURL, from_url,
372
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
373
374
    def test_win32_local_path_to_url(self):
375
        to_url = urlutils._win32_local_path_to_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
376
        self.assertEqual('file:///C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
377
            to_url('C:/path/to/foo'))
1711.4.4 by John Arbash Meinel
Fix some broken tests because of stupid ntpath.abspath behavior
378
        # BOGUS: on win32, ntpath.abspath will strip trailing
379
        #       whitespace, so this will always fail
380
        #       Though under linux, it fakes abspath support
381
        #       and thus will succeed
382
        # self.assertEqual('file:///C:/path/to/foo%20',
383
        #     to_url('C:/path/to/foo '))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
384
        self.assertEqual('file:///C:/path/to/f%20oo',
1711.4.4 by John Arbash Meinel
Fix some broken tests because of stupid ntpath.abspath behavior
385
            to_url('C:/path/to/f oo'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
386
3503.1.2 by adwi2
Permits Windows to serve all paths on all drives.
387
        self.assertEqual('file:///', to_url('/'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
388
389
        try:
390
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
391
        except UnicodeError:
392
            raise TestSkipped("local encoding cannot handle unicode")
393
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
394
        self.assertEqual('file:///D:/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
3234.3.1 by Alexander Belchenko
ensure that local_path_to_url() always returns plain string, not unicode.
395
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
396
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
397
    def test_win32_unc_path_to_url(self):
398
        to_url = urlutils._win32_local_path_to_url
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
399
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
400
            to_url(r'\\HOST\path'))
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
401
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
402
            to_url('//HOST/path'))
403
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
404
        try:
405
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
406
        except UnicodeError:
407
            raise TestSkipped("local encoding cannot handle unicode")
408
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
409
        self.assertEqual('file://HOST/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s', result)
3234.3.1 by Alexander Belchenko
ensure that local_path_to_url() always returns plain string, not unicode.
410
        self.assertFalse(isinstance(result, unicode))
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
411
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
412
    def test_win32_local_path_from_url(self):
413
        from_url = urlutils._win32_local_path_from_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
414
        self.assertEqual('C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
415
            from_url('file:///C|/path/to/foo'))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
416
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
417
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
418
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.79 by Wouter van Heyst
cleanup urlutils
419
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
3503.1.2 by adwi2
Permits Windows to serve all paths on all drives.
420
        self.assertEqual('/', from_url('file:///'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
421
422
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
423
        # Not a valid _win32 url, no drive letter
424
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
425
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
426
    def test_win32_unc_path_from_url(self):
427
        from_url = urlutils._win32_local_path_from_url
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
428
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
429
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
430
        # we want to use only 2 slashes
431
        # Firefox understand only 5 slashes in URL, but it's ugly
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
432
        self.assertRaises(InvalidURL, from_url, 'file:////HOST/path')
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
433
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
434
        self.assertRaises(InvalidURL, from_url, 'file://////HOST/path')
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
435
        # check for file://C:/ instead of file:///C:/
436
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
437
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
438
    def test_win32_extract_drive_letter(self):
1711.2.43 by John Arbash Meinel
Split out win32 specific code so that it can be tested on all platforms.
439
        extract = urlutils._win32_extract_drive_letter
440
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
441
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
442
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
443
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
444
    def test_split(self):
445
        # Test bzrlib.urlutils.split()
446
        split = urlutils.split
447
        if sys.platform == 'win32':
448
            self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
449
            self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
450
            self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
451
        else:
452
            self.assertEqual(('file:///', 'foo'), split('file:///foo'))
453
            self.assertEqual(('file:///', ''), split('file:///'))
454
455
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
456
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
457
        self.assertEqual(('http://host/path/to/foo', ''),
458
            split('http://host/path/to/foo/', exclude_trailing_slash=False))
459
        self.assertEqual(('http://host/', 'path'), split('http://host/path'))
460
        self.assertEqual(('http://host/', ''), split('http://host/'))
461
        self.assertEqual(('http://host', ''), split('http://host'))
462
        self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
463
464
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
465
            split('random+scheme://user:pass@ahost:port/path'))
466
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
467
            split('random+scheme://user:pass@ahost:port/path/'))
468
        self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
469
            split('random+scheme://user:pass@ahost:port/'))
470
471
        # relative paths
472
        self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
473
        self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
474
        self.assertEqual(('path/to/foo', ''),
475
            split('path/to/foo/', exclude_trailing_slash=False))
476
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
477
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
478
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
479
    def test_split_segment_parameters_raw(self):
480
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
481
        self.assertEquals(("/some/path", []),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
482
            split_segment_parameters_raw("/some/path"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
483
        self.assertEquals(("/some/path", ["tip"]),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
484
            split_segment_parameters_raw("/some/path,tip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
485
        self.assertEquals(("/some,dir/path", ["tip"]),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
486
            split_segment_parameters_raw("/some,dir/path,tip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
487
        self.assertEquals(("/somedir/path", ["heads%2Ftip"]),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
488
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
489
        self.assertEquals(("/somedir/path", ["heads%2Ftip", "bar"]),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
490
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
491
        self.assertEquals(("/", ["key1=val1"]),
492
            split_segment_parameters_raw(",key1=val1"))
493
        self.assertEquals(("foo/", ["key1=val1"]),
494
            split_segment_parameters_raw("foo/,key1=val1"))
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
495
        self.assertEquals(("foo/base,la=bla/other/elements", []),
496
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
497
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
498
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
499
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
500
    def test_split_segment_parameters(self):
501
        split_segment_parameters = urlutils.split_segment_parameters
502
        self.assertEquals(("/some/path", {}),
503
            split_segment_parameters("/some/path"))
504
        self.assertEquals(("/some/path", {"branch": "tip"}),
505
            split_segment_parameters("/some/path,branch=tip"))
506
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
507
            split_segment_parameters("/some,dir/path,branch=tip"))
508
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
509
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
510
        self.assertEquals(("/somedir/path",
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
511
            {"ref": "heads%2Ftip", "key1": "val1"}),
512
            split_segment_parameters(
513
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
514
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
515
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
516
        self.assertEquals(("/", {"key1": "val1"}),
517
            split_segment_parameters(",key1=val1"))
518
        self.assertEquals(("foo/", {"key1": "val1"}),
519
            split_segment_parameters("foo/,key1=val1"))
520
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
521
            split_segment_parameters("foo/base,key1=val1/other/elements"))
522
        self.assertEquals(("foo/base,key1=val1/other/elements",
523
            {"key2": "val2"}), split_segment_parameters(
524
                "foo/base,key1=val1/other/elements,key2=val2"))
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
525
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
526
    def test_win32_strip_local_trailing_slash(self):
1711.2.44 by John Arbash Meinel
Factor out another win32 special case and add platform independent tests for it.
527
        strip = urlutils._win32_strip_local_trailing_slash
528
        self.assertEqual('file://', strip('file://'))
529
        self.assertEqual('file:///', strip('file:///'))
530
        self.assertEqual('file:///C', strip('file:///C'))
531
        self.assertEqual('file:///C:', strip('file:///C:'))
532
        self.assertEqual('file:///d|', strip('file:///d|'))
533
        self.assertEqual('file:///C:/', strip('file:///C:/'))
534
        self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
535
1685.1.48 by John Arbash Meinel
Updated strip_trailing_slash to support lots more url stuff, added tests
536
    def test_strip_trailing_slash(self):
537
        sts = urlutils.strip_trailing_slash
538
        if sys.platform == 'win32':
539
            self.assertEqual('file:///C|/', sts('file:///C|/'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
540
            self.assertEqual('file:///C:/foo', sts('file:///C:/foo'))
1685.1.48 by John Arbash Meinel
Updated strip_trailing_slash to support lots more url stuff, added tests
541
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
542
        else:
543
            self.assertEqual('file:///', sts('file:///'))
544
            self.assertEqual('file:///foo', sts('file:///foo'))
545
            self.assertEqual('file:///foo', sts('file:///foo/'))
546
547
        self.assertEqual('http://host/', sts('http://host/'))
548
        self.assertEqual('http://host/foo', sts('http://host/foo'))
549
        self.assertEqual('http://host/foo', sts('http://host/foo/'))
550
551
        # No need to fail just because the slash is missing
552
        self.assertEqual('http://host', sts('http://host'))
553
        # TODO: jam 20060502 Should this raise InvalidURL?
554
        self.assertEqual('file://', sts('file://'))
555
556
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
557
            sts('random+scheme://user:pass@ahost:port/path'))
558
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
559
            sts('random+scheme://user:pass@ahost:port/path/'))
560
        self.assertEqual('random+scheme://user:pass@ahost:port/',
561
            sts('random+scheme://user:pass@ahost:port/'))
562
563
        # Make sure relative paths work too
564
        self.assertEqual('path/to/foo', sts('path/to/foo'))
565
        self.assertEqual('path/to/foo', sts('path/to/foo/'))
566
        self.assertEqual('../to/foo', sts('../to/foo/'))
567
        self.assertEqual('path/../foo', sts('path/../foo/'))
568
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
569
    def test_unescape_for_display_utf8(self):
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
570
        # Test that URLs are converted to nice unicode strings for display
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
571
        def test(expected, url, encoding='utf-8'):
572
            disp_url = urlutils.unescape_for_display(url, encoding=encoding)
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
573
            self.assertIsInstance(disp_url, unicode)
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
574
            self.assertEqual(expected, disp_url)
1685.1.79 by Wouter van Heyst
cleanup urlutils
575
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
576
        test('http://foo', 'http://foo')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
577
        if sys.platform == 'win32':
1711.7.13 by John Arbash Meinel
Fix expected value for urlutils tests
578
            test('C:/foo/path', 'file:///C|/foo/path')
579
            test('C:/foo/path', 'file:///C:/foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
580
        else:
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
581
            test('/foo/path', 'file:///foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
582
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
583
        test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
584
        test(u'http://host/r\xe4ksm\xf6rg\xe5s',
585
             'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
586
587
        # Make sure special escaped characters stay escaped
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
588
        test(u'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23',
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
589
             'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
590
591
        # Can we handle sections that don't have utf-8 encoding?
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
592
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
593
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s')
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
594
595
        # Test encoding into output that can handle some characters
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
596
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
597
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
598
             encoding='iso-8859-1')
599
600
        # This one can be encoded into utf8
601
        test(u'http://host/\u062c\u0648\u062c\u0648',
602
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
603
             encoding='utf-8')
604
605
        # This can't be put into 8859-1 and so stays as escapes
606
        test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
607
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
608
             encoding='iso-8859-1')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
609
610
    def test_escape(self):
611
        self.assertEqual('%25', urlutils.escape('%'))
612
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
3234.3.1 by Alexander Belchenko
ensure that local_path_to_url() always returns plain string, not unicode.
613
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
614
4098.3.1 by Jonathan Lange
Don't escape tildes
615
    def test_escape_tildes(self):
616
        self.assertEqual('~foo', urlutils.escape('~foo'))
617
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
618
    def test_unescape(self):
619
        self.assertEqual('%', urlutils.unescape('%25'))
620
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
621
622
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
623
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
624
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
625
626
    def test_escape_unescape(self):
627
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
628
        self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
629
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
630
    def test_relative_url(self):
631
        def test(expected, base, other):
632
            result = urlutils.relative_url(base, other)
633
            self.assertEqual(expected, result)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
634
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
635
        test('a', 'http://host/', 'http://host/a')
1685.1.71 by Wouter van Heyst
change branch.{get,set}_parent to store a relative path but return full urls
636
        test('http://entirely/different', 'sftp://host/branch',
637
                    'http://entirely/different')
638
        test('../person/feature', 'http://host/branch/mainline',
639
                    'http://host/branch/person/feature')
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
640
        test('..', 'http://host/branch', 'http://host/')
641
        test('http://host2/branch', 'http://host1/branch', 'http://host2/branch')
1685.1.71 by Wouter van Heyst
change branch.{get,set}_parent to store a relative path but return full urls
642
        test('.', 'http://host1/branch', 'http://host1/branch')
643
        test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
644
                    'file:///home/jelmer/branch/2b')
645
        test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
646
                    'sftp://host/home/jelmer/branch/2b')
1685.1.79 by Wouter van Heyst
cleanup urlutils
647
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
648
                    'http://host/home/jelmer/branch/feature/%2b')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
649
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/',
1685.1.71 by Wouter van Heyst
change branch.{get,set}_parent to store a relative path but return full urls
650
                    'http://host/home/jelmer/branch/feature/2b')
651
        # relative_url should preserve a trailing slash
652
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
653
                    'http://host/home/jelmer/branch/feature/2b/')
654
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
655
                    'http://host/home/jelmer/branch/feature/2b/')
656
657
        # TODO: treat http://host as http://host/
658
        #       relative_url is typically called from a branch.base or
659
        #       transport.base which always ends with a /
660
        #test('a', 'http://host', 'http://host/a')
661
        test('http://host/a', 'http://host', 'http://host/a')
662
        #test('.', 'http://host', 'http://host/')
663
        test('http://host/', 'http://host', 'http://host/')
664
        #test('.', 'http://host/', 'http://host')
665
        test('http://host', 'http://host/', 'http://host')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
666
3139.2.1 by Alexander Belchenko
bugfix #90847: fix problem with parent location on another logical drive
667
        # On Windows file:///C:/path/to and file:///D:/other/path
668
        # should not use relative url over the non-existent '/' directory.
669
        if sys.platform == 'win32':
670
            # on the same drive
671
            test('../../other/path',
672
                'file:///C:/path/to', 'file:///C:/other/path')
673
            #~next two tests is failed, i.e. urlutils.relative_url expects
674
            #~to see normalized file URLs?
675
            #~test('../../other/path',
676
            #~    'file:///C:/path/to', 'file:///c:/other/path')
677
            #~test('../../other/path',
678
            #~    'file:///C:/path/to', 'file:///C|/other/path')
679
680
            # check UNC paths too
681
            test('../../other/path',
682
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
683
            # on different drives
684
            test('file:///D:/other/path',
685
                'file:///C:/path/to', 'file:///D:/other/path')
686
            # TODO: strictly saying in UNC path //HOST/base is full analog
687
            # of drive letter for hard disk, and this situation is also
688
            # should be exception from rules. [bialix 20071221]
689
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
690
691
class TestCwdToURL(TestCaseInTempDir):
692
    """Test that local_path_to_url works base on the cwd"""
693
694
    def test_dot(self):
695
        # This test will fail if getcwd is not ascii
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
696
        os.mkdir('mytest')
697
        os.chdir('mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
698
699
        url = urlutils.local_path_to_url('.')
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
700
        self.assertEndsWith(url, '/mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
701
702
    def test_non_ascii(self):
2279.4.2 by Alexander Belchenko
Don't do normpath after abspath, because this function is called inside abspath
703
        if win32utils.winver == 'Windows 98':
704
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
705
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
706
        try:
707
            os.mkdir(u'dod\xe9')
708
        except UnicodeError:
709
            raise TestSkipped('cannot create unicode directory')
710
711
        os.chdir(u'dod\xe9')
712
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
713
        # On Mac OSX this directory is actually:
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
714
        #   u'/dode\u0301' => '/dode\xcc\x81
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
715
        # but we should normalize it back to
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
716
        #   u'/dod\xe9' => '/dod\xc3\xa9'
717
        url = urlutils.local_path_to_url('.')
718
        self.assertEndsWith(url, '/dod%C3%A9')
2512.4.1 by Ian Clatworthy
Fixes #115491 - 'branch lp:projname' now creates ./projname as exected
719
720
721
class TestDeriveToLocation(TestCase):
722
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
723
724
    def test_to_locations_derived_from_paths(self):
725
        derive = urlutils.derive_to_location
726
        self.assertEqual("bar", derive("bar"))
727
        self.assertEqual("bar", derive("../bar"))
728
        self.assertEqual("bar", derive("/foo/bar"))
729
        self.assertEqual("bar", derive("c:/foo/bar"))
730
        self.assertEqual("bar", derive("c:bar"))
731
732
    def test_to_locations_derived_from_urls(self):
733
        derive = urlutils.derive_to_location
734
        self.assertEqual("bar", derive("http://foo/bar"))
735
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
736
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
3242.3.26 by Aaron Bentley
Implement rebase_url
737
738
739
class TestRebaseURL(TestCase):
740
    """Test the behavior of rebase_url."""
741
742
    def test_non_relative(self):
743
        result = urlutils.rebase_url('file://foo', 'file://foo',
744
                                     'file://foo/bar')
745
        self.assertEqual('file://foo', result)
746
        result = urlutils.rebase_url('/foo', 'file://foo',
747
                                     'file://foo/bar')
748
        self.assertEqual('/foo', result)
749
3242.3.36 by Aaron Bentley
Updates from review comments
750
    def test_different_ports(self):
751
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
752
                              'foo', 'http://bar:80', 'http://bar:81')
753
        self.assertEqual(str(e), "URLs differ by more than path:"
754
                         " 'http://bar:80' and 'http://bar:81'")
755
756
    def test_different_hosts(self):
3242.3.33 by Aaron Bentley
Handle relative URL stacking cleanly
757
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
758
                              'foo', 'http://bar', 'http://baz')
759
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
760
                         " and 'http://baz'")
3242.3.26 by Aaron Bentley
Implement rebase_url
761
3242.3.36 by Aaron Bentley
Updates from review comments
762
    def test_different_protocol(self):
763
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
764
                              'foo', 'http://bar', 'ftp://bar')
765
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
766
                         " and 'ftp://bar'")
767
3242.3.26 by Aaron Bentley
Implement rebase_url
768
    def test_rebase_success(self):
769
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
770
                         'http://baz/qux'))
771
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
772
                         'http://baz/qux', 'http://baz/'))
773
        self.assertEqual('.', urlutils.rebase_url('foo',
774
                         'http://bar/', 'http://bar/foo/'))
3567.2.1 by Michael Hudson
urlutils.rebase_url handles '..' path segments in 'url'
775
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
776
                         'http://baz/qux/foo', 'http://baz/'))
3242.3.26 by Aaron Bentley
Implement rebase_url
777
778
    def test_determine_relative_path(self):
779
        self.assertEqual('../../baz/bar',
780
                         urlutils.determine_relative_path(
781
                         '/qux/quxx', '/baz/bar'))
782
        self.assertEqual('..',
783
                         urlutils.determine_relative_path(
784
                         '/bar/baz', '/bar'))
785
        self.assertEqual('baz',
786
                         urlutils.determine_relative_path(
787
                         '/bar', '/bar/baz'))
788
        self.assertEqual('.', urlutils.determine_relative_path(
789
                         '/bar', '/bar'))
3873.3.1 by Martin Pool
Move Transport._split_url to urlutils, and ad a simple test
790
791
792
class TestParseURL(TestCase):
793
794
    def test_parse_url(self):
795
        self.assertEqual(urlutils.parse_url('http://example.com:80/one'),
796
            ('http', None, None, 'example.com', 80, '/one'))
3873.3.2 by Martin Pool
Accept ipv6 literals in URLs
797
        self.assertEqual(urlutils.parse_url('http://[1:2:3::40]/one'),
798
                ('http', None, None, '1:2:3::40', None, '/one'))
799
        self.assertEqual(urlutils.parse_url('http://[1:2:3::40]:80/one'),
800
                ('http', None, None, '1:2:3::40', 80, '/one'))