/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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
5268.7.4 by Jelmer Vernooij
Only skip escaping , and = when actually necessary.
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':
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
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)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
343
        else:
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
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)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
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'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
353
5268.7.4 by Jelmer Vernooij
Only skip escaping , and = when actually necessary.
354
        self.assertEqual('file:///path/to/foo%2Cbar',
355
            to_url('/path/to/foo,bar'))
356
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
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)
3234.3.1 by Alexander Belchenko
ensure that local_path_to_url() always returns plain string, not unicode.
363
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
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'))
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
369
        self.assertEqual('/path/to/foo',
370
            from_url('file:///path/to/foo,branch=foo'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
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'))
4828.1.1 by Michael Hudson
test and fix
375
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
376
            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
377
378
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
4828.1.1 by Michael Hudson
test and fix
379
        self.assertRaises(
380
            InvalidURL, from_url,
381
            'file://remotehost/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
382
383
    def test_win32_local_path_to_url(self):
384
        to_url = urlutils._win32_local_path_to_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
385
        self.assertEqual('file:///C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
386
            to_url('C:/path/to/foo'))
1711.4.4 by John Arbash Meinel
Fix some broken tests because of stupid ntpath.abspath behavior
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 '))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
393
        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
394
            to_url('C:/path/to/f oo'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
395
3503.1.2 by adwi2
Permits Windows to serve all paths on all drives.
396
        self.assertEqual('file:///', to_url('/'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
397
5268.7.4 by Jelmer Vernooij
Only skip escaping , and = when actually necessary.
398
        self.assertEqual('file:///C:/path/to/foo%2Cbar',
399
            to_url('C:/path/to/foo,bar'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
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
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
405
        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.
406
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
407
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
408
    def test_win32_unc_path_to_url(self):
409
        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
410
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
411
            to_url(r'\\HOST\path'))
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
412
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
413
            to_url('//HOST/path'))
414
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
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
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
420
        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.
421
        self.assertFalse(isinstance(result, unicode))
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
422
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
423
    def test_win32_local_path_from_url(self):
424
        from_url = urlutils._win32_local_path_from_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
425
        self.assertEqual('C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
426
            from_url('file:///C|/path/to/foo'))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
427
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
428
            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.
429
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.79 by Wouter van Heyst
cleanup urlutils
430
            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.
431
        self.assertEqual('/', from_url('file:///'))
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
432
        self.assertEqual('C:/path/to/foo',
433
            from_url('file:///C|/path/to/foo,branch=foo'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
434
5510.2.3 by Jared Bunting
Changed _win32_local_path_from_url to not allow "file:///C:" form.
435
        self.assertRaises(InvalidURL, from_url, 'file:///C:')
5510.2.1 by Jared Bunting
Modified _win32_local_path_from_url to:
436
        self.assertRaises(InvalidURL, from_url, 'file:///c')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
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
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
441
    def test_win32_unc_path_from_url(self):
442
        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
443
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
444
        self.assertEqual('//HOST/path',
445
            from_url('file://HOST/path,branch=foo'))
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
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
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
449
        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
450
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
451
        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
452
        # check for file://C:/ instead of file:///C:/
453
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
454
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
455
    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.
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')
6123.3.1 by Martin
More comprehensive testing for urlutils._win32_extract_drive_letter
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')
1711.2.43 by John Arbash Meinel
Split out win32 specific code so that it can be tested on all platforms.
466
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
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'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
473
            self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
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
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
502
    def test_split_segment_parameters_raw(self):
503
        split_segment_parameters_raw = urlutils.split_segment_parameters_raw
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
504
        # Check relative references with absolute paths
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
505
        self.assertEquals(("/some/path", []),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
506
            split_segment_parameters_raw("/some/path"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
507
        self.assertEquals(("/some/path", ["tip"]),
5163.2.5 by Jelmer Vernooij
rename {split,join}_subsegments -> {split,join}_segment_parameters_raw and add more tests.
508
            split_segment_parameters_raw("/some/path,tip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
509
        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.
510
            split_segment_parameters_raw("/some,dir/path,tip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
511
        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.
512
            split_segment_parameters_raw("/somedir/path,heads%2Ftip"))
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
513
        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.
514
            split_segment_parameters_raw("/somedir/path,heads%2Ftip,bar"))
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
515
        # Check relative references with relative paths
6278.1.1 by Martin Packman
Correct assertions for relative paths in tests for split_segment_parameters
516
        self.assertEquals(("", ["key1=val1"]),
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
517
            split_segment_parameters_raw(",key1=val1"))
518
        self.assertEquals(("foo/", ["key1=val1"]),
519
            split_segment_parameters_raw("foo/,key1=val1"))
6278.1.1 by Martin Packman
Correct assertions for relative paths in tests for split_segment_parameters
520
        self.assertEquals(("foo", ["key1=val1"]),
5268.7.21 by Jelmer Vernooij
Cope with segment parameters in urls.
521
            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.
522
        self.assertEquals(("foo/base,la=bla/other/elements", []),
523
            split_segment_parameters_raw("foo/base,la=bla/other/elements"))
524
        self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
525
            split_segment_parameters_raw("foo/base,la=bla/other/elements,a=b"))
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
526
        # TODO: Check full URLs as well as relative references
5163.2.1 by Jelmer Vernooij
Add urlutils.split_subsegments.
527
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
528
    def test_split_segment_parameters(self):
529
        split_segment_parameters = urlutils.split_segment_parameters
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
530
        # Check relative references with absolute paths
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
531
        self.assertEquals(("/some/path", {}),
532
            split_segment_parameters("/some/path"))
533
        self.assertEquals(("/some/path", {"branch": "tip"}),
534
            split_segment_parameters("/some/path,branch=tip"))
535
        self.assertEquals(("/some,dir/path", {"branch": "tip"}),
536
            split_segment_parameters("/some,dir/path,branch=tip"))
537
        self.assertEquals(("/somedir/path", {"ref": "heads%2Ftip"}),
538
            split_segment_parameters("/somedir/path,ref=heads%2Ftip"))
539
        self.assertEquals(("/somedir/path",
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
540
            {"ref": "heads%2Ftip", "key1": "val1"}),
541
            split_segment_parameters(
542
                "/somedir/path,ref=heads%2Ftip,key1=val1"))
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
543
        self.assertEquals(("/somedir/path", {"ref": "heads%2F=tip"}),
544
            split_segment_parameters("/somedir/path,ref=heads%2F=tip"))
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
545
        # Check relative references with relative paths
6278.1.1 by Martin Packman
Correct assertions for relative paths in tests for split_segment_parameters
546
        self.assertEquals(("", {"key1": "val1"}),
5163.2.6 by Jelmer Vernooij
Fix example names in tests.
547
            split_segment_parameters(",key1=val1"))
548
        self.assertEquals(("foo/", {"key1": "val1"}),
549
            split_segment_parameters("foo/,key1=val1"))
550
        self.assertEquals(("foo/base,key1=val1/other/elements", {}),
551
            split_segment_parameters("foo/base,key1=val1/other/elements"))
552
        self.assertEquals(("foo/base,key1=val1/other/elements",
553
            {"key2": "val2"}), split_segment_parameters(
554
                "foo/base,key1=val1/other/elements,key2=val2"))
6278.1.2 by Martin Packman
Comment which checks tests for split_segment_parameters are actually doing currently
555
        # TODO: Check full URLs as well as relative references
5163.2.3 by Jelmer Vernooij
Add join_segment_parameters / split_segment_parameters.
556
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
557
    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.
558
        strip = urlutils._win32_strip_local_trailing_slash
559
        self.assertEqual('file://', strip('file://'))
560
        self.assertEqual('file:///', strip('file:///'))
561
        self.assertEqual('file:///C', strip('file:///C'))
562
        self.assertEqual('file:///C:', strip('file:///C:'))
563
        self.assertEqual('file:///d|', strip('file:///d|'))
564
        self.assertEqual('file:///C:/', strip('file:///C:/'))
565
        self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
566
1685.1.48 by John Arbash Meinel
Updated strip_trailing_slash to support lots more url stuff, added tests
567
    def test_strip_trailing_slash(self):
568
        sts = urlutils.strip_trailing_slash
569
        if sys.platform == 'win32':
570
            self.assertEqual('file:///C|/', sts('file:///C|/'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
571
            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
572
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
573
        else:
574
            self.assertEqual('file:///', sts('file:///'))
575
            self.assertEqual('file:///foo', sts('file:///foo'))
576
            self.assertEqual('file:///foo', sts('file:///foo/'))
577
578
        self.assertEqual('http://host/', sts('http://host/'))
579
        self.assertEqual('http://host/foo', sts('http://host/foo'))
580
        self.assertEqual('http://host/foo', sts('http://host/foo/'))
581
582
        # No need to fail just because the slash is missing
583
        self.assertEqual('http://host', sts('http://host'))
584
        # TODO: jam 20060502 Should this raise InvalidURL?
585
        self.assertEqual('file://', sts('file://'))
586
587
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
588
            sts('random+scheme://user:pass@ahost:port/path'))
589
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
590
            sts('random+scheme://user:pass@ahost:port/path/'))
591
        self.assertEqual('random+scheme://user:pass@ahost:port/',
592
            sts('random+scheme://user:pass@ahost:port/'))
593
594
        # Make sure relative paths work too
595
        self.assertEqual('path/to/foo', sts('path/to/foo'))
596
        self.assertEqual('path/to/foo', sts('path/to/foo/'))
597
        self.assertEqual('../to/foo', sts('../to/foo/'))
598
        self.assertEqual('path/../foo', sts('path/../foo/'))
599
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
600
    def test_unescape_for_display_utf8(self):
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
601
        # 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.
602
        def test(expected, url, encoding='utf-8'):
603
            disp_url = urlutils.unescape_for_display(url, encoding=encoding)
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
604
            self.assertIsInstance(disp_url, unicode)
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
605
            self.assertEqual(expected, disp_url)
1685.1.79 by Wouter van Heyst
cleanup urlutils
606
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
607
        test('http://foo', 'http://foo')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
608
        if sys.platform == 'win32':
1711.7.13 by John Arbash Meinel
Fix expected value for urlutils tests
609
            test('C:/foo/path', 'file:///C|/foo/path')
610
            test('C:/foo/path', 'file:///C:/foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
611
        else:
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
612
            test('/foo/path', 'file:///foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
613
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
614
        test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
615
        test(u'http://host/r\xe4ksm\xf6rg\xe5s',
616
             'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
617
618
        # 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.
619
        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
620
             '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
621
622
        # Can we handle sections that don't have utf-8 encoding?
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
623
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
624
             '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.
625
626
        # Test encoding into output that can handle some characters
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
627
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
628
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
629
             encoding='iso-8859-1')
630
631
        # This one can be encoded into utf8
632
        test(u'http://host/\u062c\u0648\u062c\u0648',
633
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
634
             encoding='utf-8')
635
636
        # This can't be put into 8859-1 and so stays as escapes
637
        test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
638
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
639
             encoding='iso-8859-1')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
640
641
    def test_escape(self):
642
        self.assertEqual('%25', urlutils.escape('%'))
643
        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.
644
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
645
4098.3.1 by Jonathan Lange
Don't escape tildes
646
    def test_escape_tildes(self):
647
        self.assertEqual('~foo', urlutils.escape('~foo'))
648
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
649
    def test_unescape(self):
650
        self.assertEqual('%', urlutils.unescape('%25'))
651
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
652
653
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
654
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
655
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
656
657
    def test_escape_unescape(self):
658
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
659
        self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
660
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
661
    def test_relative_url(self):
662
        def test(expected, base, other):
663
            result = urlutils.relative_url(base, other)
664
            self.assertEqual(expected, result)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
665
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
666
        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
667
        test('http://entirely/different', 'sftp://host/branch',
668
                    'http://entirely/different')
669
        test('../person/feature', 'http://host/branch/mainline',
670
                    'http://host/branch/person/feature')
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
671
        test('..', 'http://host/branch', 'http://host/')
672
        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
673
        test('.', 'http://host1/branch', 'http://host1/branch')
674
        test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
675
                    'file:///home/jelmer/branch/2b')
676
        test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
677
                    'sftp://host/home/jelmer/branch/2b')
1685.1.79 by Wouter van Heyst
cleanup urlutils
678
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
679
                    'http://host/home/jelmer/branch/feature/%2b')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
680
        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
681
                    'http://host/home/jelmer/branch/feature/2b')
682
        # relative_url should preserve a trailing slash
683
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
684
                    'http://host/home/jelmer/branch/feature/2b/')
685
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
686
                    'http://host/home/jelmer/branch/feature/2b/')
687
688
        # TODO: treat http://host as http://host/
689
        #       relative_url is typically called from a branch.base or
690
        #       transport.base which always ends with a /
691
        #test('a', 'http://host', 'http://host/a')
692
        test('http://host/a', 'http://host', 'http://host/a')
693
        #test('.', 'http://host', 'http://host/')
694
        test('http://host/', 'http://host', 'http://host/')
695
        #test('.', 'http://host/', 'http://host')
696
        test('http://host', 'http://host/', 'http://host')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
697
3139.2.1 by Alexander Belchenko
bugfix #90847: fix problem with parent location on another logical drive
698
        # On Windows file:///C:/path/to and file:///D:/other/path
699
        # should not use relative url over the non-existent '/' directory.
700
        if sys.platform == 'win32':
701
            # on the same drive
702
            test('../../other/path',
703
                'file:///C:/path/to', 'file:///C:/other/path')
704
            #~next two tests is failed, i.e. urlutils.relative_url expects
705
            #~to see normalized file URLs?
706
            #~test('../../other/path',
707
            #~    'file:///C:/path/to', 'file:///c:/other/path')
708
            #~test('../../other/path',
709
            #~    'file:///C:/path/to', 'file:///C|/other/path')
710
711
            # check UNC paths too
712
            test('../../other/path',
713
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
714
            # on different drives
715
            test('file:///D:/other/path',
716
                'file:///C:/path/to', 'file:///D:/other/path')
717
            # TODO: strictly saying in UNC path //HOST/base is full analog
718
            # of drive letter for hard disk, and this situation is also
719
            # should be exception from rules. [bialix 20071221]
720
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
721
722
class TestCwdToURL(TestCaseInTempDir):
723
    """Test that local_path_to_url works base on the cwd"""
724
725
    def test_dot(self):
726
        # 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
727
        os.mkdir('mytest')
728
        os.chdir('mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
729
730
        url = urlutils.local_path_to_url('.')
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
731
        self.assertEndsWith(url, '/mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
732
733
    def test_non_ascii(self):
2279.4.2 by Alexander Belchenko
Don't do normpath after abspath, because this function is called inside abspath
734
        if win32utils.winver == 'Windows 98':
735
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
736
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
737
        try:
738
            os.mkdir(u'dod\xe9')
739
        except UnicodeError:
740
            raise TestSkipped('cannot create unicode directory')
741
742
        os.chdir(u'dod\xe9')
743
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
744
        # On Mac OSX this directory is actually:
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
745
        #   u'/dode\u0301' => '/dode\xcc\x81
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
746
        # but we should normalize it back to
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
747
        #   u'/dod\xe9' => '/dod\xc3\xa9'
748
        url = urlutils.local_path_to_url('.')
749
        self.assertEndsWith(url, '/dod%C3%A9')
2512.4.1 by Ian Clatworthy
Fixes #115491 - 'branch lp:projname' now creates ./projname as exected
750
751
752
class TestDeriveToLocation(TestCase):
753
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
754
755
    def test_to_locations_derived_from_paths(self):
756
        derive = urlutils.derive_to_location
757
        self.assertEqual("bar", derive("bar"))
758
        self.assertEqual("bar", derive("../bar"))
759
        self.assertEqual("bar", derive("/foo/bar"))
760
        self.assertEqual("bar", derive("c:/foo/bar"))
761
        self.assertEqual("bar", derive("c:bar"))
762
763
    def test_to_locations_derived_from_urls(self):
764
        derive = urlutils.derive_to_location
765
        self.assertEqual("bar", derive("http://foo/bar"))
766
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
767
        self.assertEqual("foo-bar", derive("lp:foo-bar"))
3242.3.26 by Aaron Bentley
Implement rebase_url
768
769
770
class TestRebaseURL(TestCase):
771
    """Test the behavior of rebase_url."""
772
773
    def test_non_relative(self):
774
        result = urlutils.rebase_url('file://foo', 'file://foo',
775
                                     'file://foo/bar')
776
        self.assertEqual('file://foo', result)
777
        result = urlutils.rebase_url('/foo', 'file://foo',
778
                                     'file://foo/bar')
779
        self.assertEqual('/foo', result)
780
3242.3.36 by Aaron Bentley
Updates from review comments
781
    def test_different_ports(self):
782
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
783
                              'foo', 'http://bar:80', 'http://bar:81')
784
        self.assertEqual(str(e), "URLs differ by more than path:"
785
                         " 'http://bar:80' and 'http://bar:81'")
786
787
    def test_different_hosts(self):
3242.3.33 by Aaron Bentley
Handle relative URL stacking cleanly
788
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
789
                              'foo', 'http://bar', 'http://baz')
790
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
791
                         " and 'http://baz'")
3242.3.26 by Aaron Bentley
Implement rebase_url
792
3242.3.36 by Aaron Bentley
Updates from review comments
793
    def test_different_protocol(self):
794
        e = self.assertRaises(InvalidRebaseURLs, urlutils.rebase_url,
795
                              'foo', 'http://bar', 'ftp://bar')
796
        self.assertEqual(str(e), "URLs differ by more than path: 'http://bar'"
797
                         " and 'ftp://bar'")
798
3242.3.26 by Aaron Bentley
Implement rebase_url
799
    def test_rebase_success(self):
800
        self.assertEqual('../bar', urlutils.rebase_url('bar', 'http://baz/',
801
                         'http://baz/qux'))
802
        self.assertEqual('qux/bar', urlutils.rebase_url('bar',
803
                         'http://baz/qux', 'http://baz/'))
804
        self.assertEqual('.', urlutils.rebase_url('foo',
805
                         'http://bar/', 'http://bar/foo/'))
3567.2.1 by Michael Hudson
urlutils.rebase_url handles '..' path segments in 'url'
806
        self.assertEqual('qux/bar', urlutils.rebase_url('../bar',
807
                         'http://baz/qux/foo', 'http://baz/'))
3242.3.26 by Aaron Bentley
Implement rebase_url
808
809
    def test_determine_relative_path(self):
810
        self.assertEqual('../../baz/bar',
811
                         urlutils.determine_relative_path(
812
                         '/qux/quxx', '/baz/bar'))
813
        self.assertEqual('..',
814
                         urlutils.determine_relative_path(
815
                         '/bar/baz', '/bar'))
816
        self.assertEqual('baz',
817
                         urlutils.determine_relative_path(
818
                         '/bar', '/bar/baz'))
819
        self.assertEqual('.', urlutils.determine_relative_path(
820
                         '/bar', '/bar'))
3873.3.1 by Martin Pool
Move Transport._split_url to urlutils, and ad a simple test
821
822
823
class TestParseURL(TestCase):
824
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
825
    def test_parse_simple(self):
826
        parsed = urlutils.parse_url('http://example.com:80/one')
6055.2.6 by Jelmer Vernooij
Split out parse_url.
827
        self.assertEquals(('http', None, None, 'example.com', 80, '/one'),
828
            parsed)
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
829
830
    def test_ipv6(self):
831
        parsed = urlutils.parse_url('http://[1:2:3::40]/one')
6055.2.6 by Jelmer Vernooij
Split out parse_url.
832
        self.assertEquals(('http', None, None, '1:2:3::40', None, '/one'),
833
            parsed)
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
834
835
    def test_ipv6_port(self):
836
        parsed = urlutils.parse_url('http://[1:2:3::40]:80/one')
6055.2.6 by Jelmer Vernooij
Split out parse_url.
837
        self.assertEquals(('http', None, None, '1:2:3::40', 80, '/one'),
838
            parsed)
6055.2.7 by Jelmer Vernooij
Change parse_url to URL.from_string.
839
840
841
class TestURL(TestCase):
842
843
    def test_parse_simple(self):
844
        parsed = urlutils.URL.from_string('http://example.com:80/one')
845
        self.assertEquals('http', parsed.scheme)
846
        self.assertIs(None, parsed.user)
847
        self.assertIs(None, parsed.password)
848
        self.assertEquals('example.com', parsed.host)
849
        self.assertEquals(80, parsed.port)
850
        self.assertEquals('/one', parsed.path)
851
852
    def test_ipv6(self):
853
        parsed = urlutils.URL.from_string('http://[1:2:3::40]/one')
854
        self.assertEquals('http', parsed.scheme)
855
        self.assertIs(None, parsed.port)
856
        self.assertIs(None, parsed.user)
857
        self.assertIs(None, parsed.password)
858
        self.assertEquals('1:2:3::40', parsed.host)
859
        self.assertEquals('/one', parsed.path)
860
861
    def test_ipv6_port(self):
862
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
863
        self.assertEquals('http', parsed.scheme)
864
        self.assertEquals('1:2:3::40', parsed.host)
865
        self.assertIs(None, parsed.user)
866
        self.assertIs(None, parsed.password)
867
        self.assertEquals(80, parsed.port)
868
        self.assertEquals('/one', parsed.path)
869
870
    def test_quoted(self):
871
        parsed = urlutils.URL.from_string(
872
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
873
        self.assertEquals(parsed.quoted_host, 'ex%41mple.com')
874
        self.assertEquals(parsed.host, 'exAmple.com')
875
        self.assertEquals(parsed.port, 2222)
876
        self.assertEquals(parsed.quoted_user, 'ro%62ey')
877
        self.assertEquals(parsed.user, 'robey')
878
        self.assertEquals(parsed.quoted_password, 'h%40t')
879
        self.assertEquals(parsed.password, 'h@t')
880
        self.assertEquals(parsed.path, '/path')
6055.2.8 by Jelmer Vernooij
Add repr()
881
882
    def test_eq(self):
883
        parsed1 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
884
        parsed2 = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
885
        self.assertEquals(parsed1, parsed2)
886
        self.assertEquals(parsed1, parsed1)
887
        parsed2.path = '/two'
6055.2.11 by Jelmer Vernooij
Fix tests.
888
        self.assertNotEquals(parsed1, parsed2)
6055.2.8 by Jelmer Vernooij
Add repr()
889
890
    def test_repr(self):
891
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
6055.2.11 by Jelmer Vernooij
Fix tests.
892
        self.assertEquals(
893
            "<URL('http', None, None, '1:2:3::40', 80, '/one')>",
6055.2.8 by Jelmer Vernooij
Add repr()
894
            repr(parsed))
895
6055.2.13 by Jelmer Vernooij
Add URL.__str__.
896
    def test_str(self):
897
        parsed = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
898
        self.assertEquals('http://[1:2:3::40]:80/one', str(parsed))
899
6055.2.15 by Jelmer Vernooij
Add URL._combine_paths.
900
    def test__combine_paths(self):
901
        combine = urlutils.URL._combine_paths
902
        self.assertEqual('/home/sarah/project/foo',
903
                         combine('/home/sarah', 'project/foo'))
904
        self.assertEqual('/etc',
905
                         combine('/home/sarah', '../../etc'))
906
        self.assertEqual('/etc',
907
                         combine('/home/sarah', '../../../etc'))
908
        self.assertEqual('/etc',
909
                         combine('/home/sarah', '/etc'))
6055.2.17 by Jelmer Vernooij
Add URL.clone().
910
911
    def test_clone(self):
912
        url = urlutils.URL.from_string('http://[1:2:3::40]:80/one')
913
        url1 = url.clone("two")
914
        self.assertEquals("/one/two", url1.path)
915
        url2 = url.clone("/two")
916
        self.assertEquals("/two", url2.path)
917
        url3 = url.clone()
918
        self.assertIsNot(url, url3)
919
        self.assertEquals(url, url3)