/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for the urlutils wrapper."""
18
19
import os
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
20
import re
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
21
import sys
22
2279.4.2 by Alexander Belchenko
Don't do normpath after abspath, because this function is called inside abspath
23
from bzrlib import osutils, urlutils, win32utils
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
24
from bzrlib.errors import InvalidURL, InvalidURLJoin
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
25
from bzrlib.tests import TestCaseInTempDir, TestCase, TestSkipped
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
26
27
28
class TestUrlToPath(TestCase):
29
    
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
30
    def test_basename(self):
31
        # bzrlib.urlutils.basename
32
        # Test bzrlib.urlutils.split()
33
        basename = urlutils.basename
34
        if sys.platform == 'win32':
35
            self.assertRaises(InvalidURL, basename, 'file:///path/to/foo')
36
            self.assertEqual('foo', basename('file:///C|/foo'))
1685.1.78 by Wouter van Heyst
more code cleanup
37
            self.assertEqual('foo', basename('file:///C:/foo'))
38
            self.assertEqual('', basename('file:///C:/'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
39
        else:
40
            self.assertEqual('foo', basename('file:///foo'))
41
            self.assertEqual('', basename('file:///'))
42
43
        self.assertEqual('foo', basename('http://host/path/to/foo'))
44
        self.assertEqual('foo', basename('http://host/path/to/foo/'))
45
        self.assertEqual('',
46
            basename('http://host/path/to/foo/', exclude_trailing_slash=False))
47
        self.assertEqual('path', basename('http://host/path'))
48
        self.assertEqual('', basename('http://host/'))
49
        self.assertEqual('', basename('http://host'))
50
        self.assertEqual('path', basename('http:///nohost/path'))
51
52
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path'))
53
        self.assertEqual('path', basename('random+scheme://user:pass@ahost:port/path/'))
54
        self.assertEqual('', basename('random+scheme://user:pass@ahost:port/'))
55
56
        # relative paths
57
        self.assertEqual('foo', basename('path/to/foo'))
58
        self.assertEqual('foo', basename('path/to/foo/'))
59
        self.assertEqual('', basename('path/to/foo/',
60
            exclude_trailing_slash=False))
61
        self.assertEqual('foo', basename('path/../foo'))
62
        self.assertEqual('foo', basename('../path/foo'))
63
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
64
    def test_normalize_url_files(self):
65
        # Test that local paths are properly normalized
66
        normalize_url = urlutils.normalize_url
67
68
        def norm_file(expected, path):
69
            url = normalize_url(path)
70
            self.assertStartsWith(url, 'file:///')
71
            if sys.platform == 'win32':
72
                url = url[len('file:///C:'):]
73
            else:
74
                url = url[len('file://'):]
75
1685.1.53 by John Arbash Meinel
Updated normalize_url
76
            self.assertEndsWith(url, expected)
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
77
78
        norm_file('path/to/foo', 'path/to/foo')
79
        norm_file('/path/to/foo', '/path/to/foo')
80
        norm_file('path/to/foo', '../path/to/foo')
81
82
        # Local paths are assumed to *not* be escaped at all
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
83
        try:
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
84
            u'uni/\xb5'.encode(osutils.get_user_encoding())
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
85
        except UnicodeError:
86
            # locale cannot handle unicode 
87
            pass
88
        else:
89
            norm_file('uni/%C2%B5', u'uni/\xb5')
90
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
91
        norm_file('uni/%25C2%25B5', u'uni/%C2%B5')
92
        norm_file('uni/%20b', u'uni/ b')
93
        # 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
94
        # The ' ' character must not be at the end, because on win32
95
        # it gets stripped off by ntpath.abspath
96
        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.
97
98
    def test_normalize_url_hybrid(self):
99
        # Anything with a scheme:// should be treated as a hybrid url
100
        # which changes what characters get escaped.
101
        normalize_url = urlutils.normalize_url
102
103
        eq = self.assertEqual
104
        eq('file:///foo/', normalize_url(u'file:///foo/'))
105
        eq('file:///foo/%20', normalize_url(u'file:///foo/ '))
106
        eq('file:///foo/%20', normalize_url(u'file:///foo/%20'))
107
        # Don't escape reserved characters
108
        eq('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$',
109
            normalize_url('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
110
        eq('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$',
111
            normalize_url('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
112
113
        # Escape unicode characters, but not already escaped chars
114
        eq('http://host/ab/%C2%B5/%C2%B5',
115
            normalize_url(u'http://host/ab/%C2%B5/\xb5'))
116
2208.4.1 by Andrew Bennetts
normalize_url should normalise escaping of unreserved characters, like '~'.
117
        # Unescape characters that don't need to be escaped
118
        eq('http://host/~bob%2525-._',
119
                normalize_url('http://host/%7Ebob%2525%2D%2E%5F'))
120
        eq('http://host/~bob%2525-._',
121
                normalize_url(u'http://host/%7Ebob%2525%2D%2E%5F'))
122
1685.1.51 by John Arbash Meinel
Working on getting normalize_url working.
123
        # Normalize verifies URLs when they are not unicode
124
        # (indicating they did not come from the user)
125
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
126
        self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
1685.1.50 by John Arbash Meinel
Added an re for handling scheme paths.
127
128
    def test_url_scheme_re(self):
129
        # Test paths that may be URLs
130
        def test_one(url, scheme_and_path):
131
            """Assert that _url_scheme_re correctly matches
132
133
            :param scheme_and_path: The (scheme, path) that should be matched
134
                can be None, to indicate it should not match
135
            """
136
            m = urlutils._url_scheme_re.match(url)
137
            if scheme_and_path is None:
138
                self.assertEqual(None, m)
139
            else:
140
                self.assertEqual(scheme_and_path[0], m.group('scheme'))
141
                self.assertEqual(scheme_and_path[1], m.group('path'))
142
143
        # Local paths
144
        test_one('/path', None)
145
        test_one('C:/path', None)
146
        test_one('../path/to/foo', None)
147
        test_one(u'../path/to/fo\xe5', None)
148
149
        # Real URLS
150
        test_one('http://host/path/', ('http', 'host/path/'))
151
        test_one('sftp://host/path/to/foo', ('sftp', 'host/path/to/foo'))
152
        test_one('file:///usr/bin', ('file', '/usr/bin'))
153
        test_one('file:///C:/Windows', ('file', '/C:/Windows'))
154
        test_one('file:///C|/Windows', ('file', '/C|/Windows'))
155
        test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
156
157
        # Weird stuff
158
        # Can't have slashes or colons in the scheme
159
        test_one('/path/to/://foo', None)
160
        test_one('path:path://foo', None)
161
        # Must have more than one character for scheme
162
        test_one('C://foo', None)
163
        test_one('ab://foo', ('ab', 'foo'))
164
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
165
    def test_dirname(self):
166
        # Test bzrlib.urlutils.dirname()
167
        dirname = urlutils.dirname
168
        if sys.platform == 'win32':
169
            self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
170
            self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
171
            self.assertEqual('file:///C|/', dirname('file:///C|/'))
172
        else:
173
            self.assertEqual('file:///', dirname('file:///foo'))
174
            self.assertEqual('file:///', dirname('file:///'))
175
176
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
177
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
178
        self.assertEqual('http://host/path/to/foo',
179
            dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
180
        self.assertEqual('http://host/', dirname('http://host/path'))
181
        self.assertEqual('http://host/', dirname('http://host/'))
182
        self.assertEqual('http://host', dirname('http://host'))
183
        self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
184
185
        self.assertEqual('random+scheme://user:pass@ahost:port/',
186
            dirname('random+scheme://user:pass@ahost:port/path'))
187
        self.assertEqual('random+scheme://user:pass@ahost:port/',
188
            dirname('random+scheme://user:pass@ahost:port/path/'))
189
        self.assertEqual('random+scheme://user:pass@ahost:port/',
190
            dirname('random+scheme://user:pass@ahost:port/'))
191
192
        # relative paths
193
        self.assertEqual('path/to', dirname('path/to/foo'))
194
        self.assertEqual('path/to', dirname('path/to/foo/'))
195
        self.assertEqual('path/to/foo',
196
            dirname('path/to/foo/', exclude_trailing_slash=False))
197
        self.assertEqual('path/..', dirname('path/../foo'))
198
        self.assertEqual('../path', dirname('../path/foo'))
199
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
200
    def test_join(self):
201
        def test(expected, *args):
202
            joined = urlutils.join(*args)
203
            self.assertEqual(expected, joined)
204
205
        # Test relative path joining
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
206
        test('foo', 'foo') # relative fragment with nothing is preserved.
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
207
        test('foo/bar', 'foo', 'bar')
208
        test('http://foo/bar', 'http://foo', 'bar')
209
        test('http://foo/bar', 'http://foo', '.', 'bar')
210
        test('http://foo/baz', 'http://foo', 'bar', '../baz')
211
        test('http://foo/bar/baz', 'http://foo', 'bar/baz')
212
        test('http://foo/baz', 'http://foo', 'bar/../baz')
2018.5.93 by Andrew Bennetts
Fix another bug in urlutils.join.
213
        test('http://foo/baz', 'http://foo/bar/', '../baz')
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
214
215
        # Absolute paths
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
216
        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
217
        test('http://bar', 'http://foo', 'http://bar')
218
        test('sftp://bzr/foo', 'http://foo', 'bar', 'sftp://bzr/foo')
219
        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.
220
        test('http://bar/', 'http://foo', 'http://bar/')
221
        test('http://bar/a', 'http://foo', 'http://bar/a')
222
        test('http://bar/a/', 'http://foo', 'http://bar/a/')
1711.2.49 by John Arbash Meinel
urlutils.join should work for root paths.
223
224
        # From a base path
225
        test('file:///foo', 'file:///', 'foo')
226
        test('file:///bar/foo', 'file:///bar/', 'foo')
227
        test('http://host/foo', 'http://host/', 'foo')
228
        test('http://host/', 'http://host', '')
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
229
        
230
        # Invalid joinings
231
        # Cannot go above root
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
232
        # Implicitly at root:
1685.1.55 by John Arbash Meinel
Adding bzrlib.urlutils.join() to handle joining URLs
233
        self.assertRaises(InvalidURLJoin, urlutils.join,
234
                'http://foo', '../baz')
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
235
        self.assertRaises(InvalidURLJoin, urlutils.join,
236
                'http://foo', '/..')
2018.5.100 by Andrew Bennetts
Fix IndexError in urlutils.join with 'http://host/a' and '../../b'.
237
        # Joining from a path explicitly under the root.
238
        self.assertRaises(InvalidURLJoin, urlutils.join,
239
                'http://foo/a', '../../b')
2379.1.1 by Robert Collins
urlutils improvements from hpss.
240
2018.5.46 by Andrew Bennetts
Fix ChrootTransportDecorator's clone to pass less surprising offsets to the decorated transport's clone.
241
    def test_joinpath(self):
242
        def test(expected, *args):
243
            joined = urlutils.joinpath(*args)
244
            self.assertEqual(expected, joined)
245
246
        # Test a single element
247
        test('foo', 'foo')
248
249
        # Test relative path joining
250
        test('foo/bar', 'foo', 'bar')
251
        test('foo/bar', 'foo', '.', 'bar')
252
        test('foo/baz', 'foo', 'bar', '../baz')
253
        test('foo/bar/baz', 'foo', 'bar/baz')
254
        test('foo/baz', 'foo', 'bar/../baz')
255
256
        # Test joining to an absolute path
257
        test('/foo', '/foo')
258
        test('/foo', '/foo', '.')
259
        test('/foo/bar', '/foo', 'bar')
260
        test('/', '/foo', '..')
261
262
        # Test joining with an absolute path
263
        test('/bar', 'foo', '/bar')
2018.5.53 by Andrew Bennetts
Small fix to urlutils.joinpath that was causing a misbehaviour in
264
265
        # Test joining to a path with a trailing slash
266
        test('foo/bar', 'foo/', 'bar')
2018.5.46 by Andrew Bennetts
Fix ChrootTransportDecorator's clone to pass less surprising offsets to the decorated transport's clone.
267
        
268
        # Invalid joinings
269
        # Cannot go above root
270
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '../baz')
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
271
        self.assertRaises(InvalidURLJoin, urlutils.joinpath, '/', '..')
272
        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.
273
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
274
    def test_function_type(self):
275
        if sys.platform == 'win32':
276
            self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
277
            self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
278
        else:
279
            self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
280
            self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
281
282
    def test_posix_local_path_to_url(self):
283
        to_url = urlutils._posix_local_path_to_url
284
        self.assertEqual('file:///path/to/foo',
285
            to_url('/path/to/foo'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
286
287
        try:
288
            result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
289
        except UnicodeError:
290
            raise TestSkipped("local encoding cannot handle unicode")
291
292
        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.
293
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
294
295
    def test_posix_local_path_from_url(self):
296
        from_url = urlutils._posix_local_path_from_url
297
        self.assertEqual('/path/to/foo',
298
            from_url('file:///path/to/foo'))
299
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
300
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
301
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
302
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
303
304
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
305
306
    def test_win32_local_path_to_url(self):
307
        to_url = urlutils._win32_local_path_to_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
308
        self.assertEqual('file:///C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
309
            to_url('C:/path/to/foo'))
1711.4.4 by John Arbash Meinel
Fix some broken tests because of stupid ntpath.abspath behavior
310
        # BOGUS: on win32, ntpath.abspath will strip trailing
311
        #       whitespace, so this will always fail
312
        #       Though under linux, it fakes abspath support
313
        #       and thus will succeed
314
        # self.assertEqual('file:///C:/path/to/foo%20',
315
        #     to_url('C:/path/to/foo '))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
316
        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
317
            to_url('C:/path/to/f oo'))
1685.1.75 by Wouter van Heyst
more tests handle LANG=C
318
319
        try:
320
            result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
321
        except UnicodeError:
322
            raise TestSkipped("local encoding cannot handle unicode")
323
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
324
        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.
325
        self.assertFalse(isinstance(result, unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
326
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
327
    def test_win32_unc_path_to_url(self):
328
        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
329
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
330
            to_url(r'\\HOST\path'))
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
331
        self.assertEqual('file://HOST/path',
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
332
            to_url('//HOST/path'))
333
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
334
        try:
335
            result = to_url(u'//HOST/path/to/r\xe4ksm\xf6rg\xe5s')
336
        except UnicodeError:
337
            raise TestSkipped("local encoding cannot handle unicode")
338
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
339
        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.
340
        self.assertFalse(isinstance(result, unicode))
2162.2.5 by Alexander Belchenko
Expand test_win32_unc_path_to_url to check unicode
341
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
342
    def test_win32_local_path_from_url(self):
343
        from_url = urlutils._win32_local_path_from_url
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
344
        self.assertEqual('C:/path/to/foo',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
345
            from_url('file:///C|/path/to/foo'))
1711.4.28 by John Arbash Meinel
Update the test suite for Alexander's patch.
346
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
347
            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.
348
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.79 by Wouter van Heyst
cleanup urlutils
349
            from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
350
351
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
352
        # Not a valid _win32 url, no drive letter
353
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
354
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
355
    def test_win32_unc_path_from_url(self):
356
        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
357
        self.assertEqual('//HOST/path', from_url('file://HOST/path'))
358
        # despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
359
        # we want to use only 2 slashes
360
        # Firefox understand only 5 slashes in URL, but it's ugly
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
361
        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
362
        self.assertRaises(InvalidURL, from_url, 'file://///HOST/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
363
        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
364
        # check for file://C:/ instead of file:///C:/
365
        self.assertRaises(InvalidURL, from_url, 'file://C:/path')
2162.2.1 by Alexander Belchenko
Testing UNC path conversion
366
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
367
    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.
368
        extract = urlutils._win32_extract_drive_letter
369
        self.assertEqual(('file:///C:', '/foo'), extract('file://', '/C:/foo'))
370
        self.assertEqual(('file:///d|', '/path'), extract('file://', '/d|/path'))
371
        self.assertRaises(InvalidURL, extract, 'file://', '/path')
372
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
373
    def test_split(self):
374
        # Test bzrlib.urlutils.split()
375
        split = urlutils.split
376
        if sys.platform == 'win32':
377
            self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
378
            self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
379
            self.assertEqual(('file:///C:/', ''), split('file:///C:/'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
380
        else:
381
            self.assertEqual(('file:///', 'foo'), split('file:///foo'))
382
            self.assertEqual(('file:///', ''), split('file:///'))
383
384
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
385
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
386
        self.assertEqual(('http://host/path/to/foo', ''),
387
            split('http://host/path/to/foo/', exclude_trailing_slash=False))
388
        self.assertEqual(('http://host/', 'path'), split('http://host/path'))
389
        self.assertEqual(('http://host/', ''), split('http://host/'))
390
        self.assertEqual(('http://host', ''), split('http://host'))
391
        self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
392
393
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
394
            split('random+scheme://user:pass@ahost:port/path'))
395
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
396
            split('random+scheme://user:pass@ahost:port/path/'))
397
        self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
398
            split('random+scheme://user:pass@ahost:port/'))
399
400
        # relative paths
401
        self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
402
        self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
403
        self.assertEqual(('path/to/foo', ''),
404
            split('path/to/foo/', exclude_trailing_slash=False))
405
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
406
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
407
2162.2.6 by Alexander Belchenko
Change tests for win32 UNC path to new file://HOST/path scheme
408
    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.
409
        strip = urlutils._win32_strip_local_trailing_slash
410
        self.assertEqual('file://', strip('file://'))
411
        self.assertEqual('file:///', strip('file:///'))
412
        self.assertEqual('file:///C', strip('file:///C'))
413
        self.assertEqual('file:///C:', strip('file:///C:'))
414
        self.assertEqual('file:///d|', strip('file:///d|'))
415
        self.assertEqual('file:///C:/', strip('file:///C:/'))
416
        self.assertEqual('file:///C:/a', strip('file:///C:/a/'))
417
1685.1.48 by John Arbash Meinel
Updated strip_trailing_slash to support lots more url stuff, added tests
418
    def test_strip_trailing_slash(self):
419
        sts = urlutils.strip_trailing_slash
420
        if sys.platform == 'win32':
421
            self.assertEqual('file:///C|/', sts('file:///C|/'))
1685.1.79 by Wouter van Heyst
cleanup urlutils
422
            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
423
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
424
        else:
425
            self.assertEqual('file:///', sts('file:///'))
426
            self.assertEqual('file:///foo', sts('file:///foo'))
427
            self.assertEqual('file:///foo', sts('file:///foo/'))
428
429
        self.assertEqual('http://host/', sts('http://host/'))
430
        self.assertEqual('http://host/foo', sts('http://host/foo'))
431
        self.assertEqual('http://host/foo', sts('http://host/foo/'))
432
433
        # No need to fail just because the slash is missing
434
        self.assertEqual('http://host', sts('http://host'))
435
        # TODO: jam 20060502 Should this raise InvalidURL?
436
        self.assertEqual('file://', sts('file://'))
437
438
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
439
            sts('random+scheme://user:pass@ahost:port/path'))
440
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
441
            sts('random+scheme://user:pass@ahost:port/path/'))
442
        self.assertEqual('random+scheme://user:pass@ahost:port/',
443
            sts('random+scheme://user:pass@ahost:port/'))
444
445
        # Make sure relative paths work too
446
        self.assertEqual('path/to/foo', sts('path/to/foo'))
447
        self.assertEqual('path/to/foo', sts('path/to/foo/'))
448
        self.assertEqual('../to/foo', sts('../to/foo/'))
449
        self.assertEqual('path/../foo', sts('path/../foo/'))
450
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
451
    def test_unescape_for_display_utf8(self):
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
452
        # 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.
453
        def test(expected, url, encoding='utf-8'):
454
            disp_url = urlutils.unescape_for_display(url, encoding=encoding)
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
455
            self.assertIsInstance(disp_url, unicode)
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
456
            self.assertEqual(expected, disp_url)
1685.1.79 by Wouter van Heyst
cleanup urlutils
457
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
458
        test('http://foo', 'http://foo')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
459
        if sys.platform == 'win32':
1711.7.13 by John Arbash Meinel
Fix expected value for urlutils tests
460
            test('C:/foo/path', 'file:///C|/foo/path')
461
            test('C:/foo/path', 'file:///C:/foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
462
        else:
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
463
            test('/foo/path', 'file:///foo/path')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
464
1685.1.54 by John Arbash Meinel
url_for_display now makes sure output can be properly encoded.
465
        test('http://foo/%2Fbaz', 'http://foo/%2Fbaz')
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
466
        test(u'http://host/r\xe4ksm\xf6rg\xe5s',
467
             'http://host/r%C3%A4ksm%C3%B6rg%C3%A5s')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
468
469
        # 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.
470
        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
471
             '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
472
473
        # Can we handle sections that don't have utf-8 encoding?
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
474
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
475
             '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.
476
477
        # Test encoding into output that can handle some characters
1685.1.58 by Martin Pool
urlutils.unescape_for_display should return Unicode
478
        test(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
479
             'http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s',
480
             encoding='iso-8859-1')
481
482
        # This one can be encoded into utf8
483
        test(u'http://host/\u062c\u0648\u062c\u0648',
484
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
485
             encoding='utf-8')
486
487
        # This can't be put into 8859-1 and so stays as escapes
488
        test(u'http://host/%d8%ac%d9%88%d8%ac%d9%88',
489
             'http://host/%d8%ac%d9%88%d8%ac%d9%88',
490
             encoding='iso-8859-1')
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
491
492
    def test_escape(self):
493
        self.assertEqual('%25', urlutils.escape('%'))
494
        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.
495
        self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
496
497
    def test_unescape(self):
498
        self.assertEqual('%', urlutils.unescape('%25'))
499
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
500
501
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
502
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
503
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
504
505
    def test_escape_unescape(self):
506
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
507
        self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
508
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
509
    def test_relative_url(self):
510
        def test(expected, base, other):
511
            result = urlutils.relative_url(base, other)
512
            self.assertEqual(expected, result)
513
            
514
        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
515
        test('http://entirely/different', 'sftp://host/branch',
516
                    'http://entirely/different')
517
        test('../person/feature', 'http://host/branch/mainline',
518
                    'http://host/branch/person/feature')
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
519
        test('..', 'http://host/branch', 'http://host/')
520
        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
521
        test('.', 'http://host1/branch', 'http://host1/branch')
522
        test('../../../branch/2b', 'file:///home/jelmer/foo/bar/2b',
523
                    'file:///home/jelmer/branch/2b')
524
        test('../../branch/2b', 'sftp://host/home/jelmer/bar/2b',
525
                    'sftp://host/home/jelmer/branch/2b')
1685.1.79 by Wouter van Heyst
cleanup urlutils
526
        test('../../branch/feature/%2b', 'http://host/home/jelmer/bar/%2b',
527
                    'http://host/home/jelmer/branch/feature/%2b')
1685.1.71 by Wouter van Heyst
change branch.{get,set}_parent to store a relative path but return full urls
528
        test('../../branch/feature/2b', 'http://host/home/jelmer/bar/2b/', 
529
                    'http://host/home/jelmer/branch/feature/2b')
530
        # relative_url should preserve a trailing slash
531
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b/',
532
                    'http://host/home/jelmer/branch/feature/2b/')
533
        test('../../branch/feature/2b/', 'http://host/home/jelmer/bar/2b',
534
                    'http://host/home/jelmer/branch/feature/2b/')
535
536
        # TODO: treat http://host as http://host/
537
        #       relative_url is typically called from a branch.base or
538
        #       transport.base which always ends with a /
539
        #test('a', 'http://host', 'http://host/a')
540
        test('http://host/a', 'http://host', 'http://host/a')
541
        #test('.', 'http://host', 'http://host/')
542
        test('http://host/', 'http://host', 'http://host/')
543
        #test('.', 'http://host/', 'http://host')
544
        test('http://host', 'http://host/', 'http://host')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
545
3139.2.1 by Alexander Belchenko
bugfix #90847: fix problem with parent location on another logical drive
546
        # On Windows file:///C:/path/to and file:///D:/other/path
547
        # should not use relative url over the non-existent '/' directory.
548
        if sys.platform == 'win32':
549
            # on the same drive
550
            test('../../other/path',
551
                'file:///C:/path/to', 'file:///C:/other/path')
552
            #~next two tests is failed, i.e. urlutils.relative_url expects
553
            #~to see normalized file URLs?
554
            #~test('../../other/path',
555
            #~    'file:///C:/path/to', 'file:///c:/other/path')
556
            #~test('../../other/path',
557
            #~    'file:///C:/path/to', 'file:///C|/other/path')
558
559
            # check UNC paths too
560
            test('../../other/path',
561
                'file://HOST/base/path/to', 'file://HOST/base/other/path')
562
            # on different drives
563
            test('file:///D:/other/path',
564
                'file:///C:/path/to', 'file:///D:/other/path')
565
            # TODO: strictly saying in UNC path //HOST/base is full analog
566
            # of drive letter for hard disk, and this situation is also
567
            # should be exception from rules. [bialix 20071221]
568
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
569
570
class TestCwdToURL(TestCaseInTempDir):
571
    """Test that local_path_to_url works base on the cwd"""
572
573
    def test_dot(self):
574
        # 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
575
        os.mkdir('mytest')
576
        os.chdir('mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
577
578
        url = urlutils.local_path_to_url('.')
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
579
        self.assertEndsWith(url, '/mytest')
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
580
581
    def test_non_ascii(self):
2279.4.2 by Alexander Belchenko
Don't do normpath after abspath, because this function is called inside abspath
582
        if win32utils.winver == 'Windows 98':
583
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
584
1830.3.13 by John Arbash Meinel
Add a test that urlutils creates normalized paths
585
        try:
586
            os.mkdir(u'dod\xe9')
587
        except UnicodeError:
588
            raise TestSkipped('cannot create unicode directory')
589
590
        os.chdir(u'dod\xe9')
591
592
        # On Mac OSX this directory is actually: 
593
        #   u'/dode\u0301' => '/dode\xcc\x81
594
        # but we should normalize it back to 
595
        #   u'/dod\xe9' => '/dod\xc3\xa9'
596
        url = urlutils.local_path_to_url('.')
597
        self.assertEndsWith(url, '/dod%C3%A9')
2512.4.1 by Ian Clatworthy
Fixes #115491 - 'branch lp:projname' now creates ./projname as exected
598
599
600
class TestDeriveToLocation(TestCase):
601
    """Test that the mapping of FROM_LOCATION to TO_LOCATION works."""
602
603
    def test_to_locations_derived_from_paths(self):
604
        derive = urlutils.derive_to_location
605
        self.assertEqual("bar", derive("bar"))
606
        self.assertEqual("bar", derive("../bar"))
607
        self.assertEqual("bar", derive("/foo/bar"))
608
        self.assertEqual("bar", derive("c:/foo/bar"))
609
        self.assertEqual("bar", derive("c:bar"))
610
611
    def test_to_locations_derived_from_urls(self):
612
        derive = urlutils.derive_to_location
613
        self.assertEqual("bar", derive("http://foo/bar"))
614
        self.assertEqual("bar", derive("bzr+ssh://foo/bar"))
615
        self.assertEqual("foo-bar", derive("lp:foo-bar"))