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