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