/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1
# Copyright (C) 2005 by Canonical Ltd
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
20
import sys
21
22
import bzrlib
23
from bzrlib.errors import InvalidURL
24
import bzrlib.urlutils as urlutils
25
from bzrlib.tests import TestCaseInTempDir, TestCase
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'))
37
            self.assertEqual('', basename('file:///C|/'))
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
75
            self.assertEndsWith(path, expected)
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
82
        norm_file('uni/%C2%B5', u'uni/\xb5')
83
        norm_file('uni/%25C2%25B5', u'uni/%C2%B5')
84
        norm_file('uni/%20b', u'uni/ b')
85
        # All the crazy characters get escaped in local paths => file:/// urls
86
        norm_file('%27%3B/%3F%3A%40%26%3D%2B%24%2C%23%20', "';/?:@&=+$,#")
87
88
    def test_normalize_url_hybrid(self):
89
        # Anything with a scheme:// should be treated as a hybrid url
90
        # which changes what characters get escaped.
91
        normalize_url = urlutils.normalize_url
92
93
        eq = self.assertEqual
94
        eq('file:///foo/', normalize_url(u'file:///foo/'))
95
        eq('file:///foo/%20', normalize_url(u'file:///foo/ '))
96
        eq('file:///foo/%20', normalize_url(u'file:///foo/%20'))
97
        # Don't escape reserved characters
98
        eq('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$',
99
            normalize_url('file:///ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
100
        eq('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$',
101
            normalize_url('http://ab_c.d-e/%f:?g&h=i+j;k,L#M$'))
102
103
        # Escape unicode characters, but not already escaped chars
104
        eq('http://host/ab/%C2%B5/%C2%B5',
105
            normalize_url(u'http://host/ab/%C2%B5/\xb5'))
106
107
        # Normalize verifies URLs when they are not unicode
108
        # (indicating they did not come from the user)
109
        self.assertRaises(InvalidURL, normalize_url, 'http://host/\xb5')
110
        self.assertRaises(InvalidURL, normalize_url, 'http://host/ ')
1685.1.50 by John Arbash Meinel
Added an re for handling scheme paths.
111
112
    def test_url_scheme_re(self):
113
        # Test paths that may be URLs
114
        def test_one(url, scheme_and_path):
115
            """Assert that _url_scheme_re correctly matches
116
117
            :param scheme_and_path: The (scheme, path) that should be matched
118
                can be None, to indicate it should not match
119
            """
120
            m = urlutils._url_scheme_re.match(url)
121
            if scheme_and_path is None:
122
                self.assertEqual(None, m)
123
            else:
124
                self.assertEqual(scheme_and_path[0], m.group('scheme'))
125
                self.assertEqual(scheme_and_path[1], m.group('path'))
126
127
        # Local paths
128
        test_one('/path', None)
129
        test_one('C:/path', None)
130
        test_one('../path/to/foo', None)
131
        test_one(u'../path/to/fo\xe5', None)
132
133
        # Real URLS
134
        test_one('http://host/path/', ('http', 'host/path/'))
135
        test_one('sftp://host/path/to/foo', ('sftp', 'host/path/to/foo'))
136
        test_one('file:///usr/bin', ('file', '/usr/bin'))
137
        test_one('file:///C:/Windows', ('file', '/C:/Windows'))
138
        test_one('file:///C|/Windows', ('file', '/C|/Windows'))
139
        test_one(u'readonly+sftp://host/path/\xe5', ('readonly+sftp', u'host/path/\xe5'))
140
141
        # Weird stuff
142
        # Can't have slashes or colons in the scheme
143
        test_one('/path/to/://foo', None)
144
        test_one('path:path://foo', None)
145
        # Must have more than one character for scheme
146
        test_one('C://foo', None)
147
        test_one('ab://foo', ('ab', 'foo'))
148
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
149
    def test_dirname(self):
150
        # Test bzrlib.urlutils.dirname()
151
        dirname = urlutils.dirname
152
        if sys.platform == 'win32':
153
            self.assertRaises(InvalidURL, dirname, 'file:///path/to/foo')
154
            self.assertEqual('file:///C|/', dirname('file:///C|/foo'))
155
            self.assertEqual('file:///C|/', dirname('file:///C|/'))
156
        else:
157
            self.assertEqual('file:///', dirname('file:///foo'))
158
            self.assertEqual('file:///', dirname('file:///'))
159
160
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo'))
161
        self.assertEqual('http://host/path/to', dirname('http://host/path/to/foo/'))
162
        self.assertEqual('http://host/path/to/foo',
163
            dirname('http://host/path/to/foo/', exclude_trailing_slash=False))
164
        self.assertEqual('http://host/', dirname('http://host/path'))
165
        self.assertEqual('http://host/', dirname('http://host/'))
166
        self.assertEqual('http://host', dirname('http://host'))
167
        self.assertEqual('http:///nohost', dirname('http:///nohost/path'))
168
169
        self.assertEqual('random+scheme://user:pass@ahost:port/',
170
            dirname('random+scheme://user:pass@ahost:port/path'))
171
        self.assertEqual('random+scheme://user:pass@ahost:port/',
172
            dirname('random+scheme://user:pass@ahost:port/path/'))
173
        self.assertEqual('random+scheme://user:pass@ahost:port/',
174
            dirname('random+scheme://user:pass@ahost:port/'))
175
176
        # relative paths
177
        self.assertEqual('path/to', dirname('path/to/foo'))
178
        self.assertEqual('path/to', dirname('path/to/foo/'))
179
        self.assertEqual('path/to/foo',
180
            dirname('path/to/foo/', exclude_trailing_slash=False))
181
        self.assertEqual('path/..', dirname('path/../foo'))
182
        self.assertEqual('../path', dirname('../path/foo'))
183
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
184
    def test_function_type(self):
185
        if sys.platform == 'win32':
186
            self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
187
            self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
188
        else:
189
            self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
190
            self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
191
192
    def test_posix_local_path_to_url(self):
193
        to_url = urlutils._posix_local_path_to_url
194
        self.assertEqual('file:///path/to/foo',
195
            to_url('/path/to/foo'))
196
        self.assertEqual('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s',
197
            to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s'))
198
199
    def test_posix_local_path_from_url(self):
200
        from_url = urlutils._posix_local_path_from_url
201
        self.assertEqual('/path/to/foo',
202
            from_url('file:///path/to/foo'))
203
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
204
            from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
205
        self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
206
            from_url('file:///path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
207
208
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
209
210
    def test_win32_local_path_to_url(self):
211
        to_url = urlutils._win32_local_path_to_url
212
        self.assertEqual('file:///C|/path/to/foo',
213
            to_url('C:/path/to/foo'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
214
        self.assertEqual('file:///D|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
215
            to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s'))
216
217
    def test_win32_local_path_from_url(self):
218
        from_url = urlutils._win32_local_path_from_url
219
        self.assertEqual('C:/path/to/foo',
220
            from_url('file:///C|/path/to/foo'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
221
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
222
            from_url('file:///d|/path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
223
        self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
224
            from_url('file:///d|/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
225
226
        self.assertRaises(InvalidURL, from_url, '/path/to/foo')
227
        # Not a valid _win32 url, no drive letter
228
        self.assertRaises(InvalidURL, from_url, 'file:///path/to/foo')
229
1685.1.49 by John Arbash Meinel
Added bzrlib.urlutils.split and basename + dirname
230
    def test_split(self):
231
        # Test bzrlib.urlutils.split()
232
        split = urlutils.split
233
        if sys.platform == 'win32':
234
            self.assertRaises(InvalidURL, split, 'file:///path/to/foo')
235
            self.assertEqual(('file:///C|/', 'foo'), split('file:///C|/foo'))
236
            self.assertEqual(('file:///C|/', ''), split('file:///C|/'))
237
        else:
238
            self.assertEqual(('file:///', 'foo'), split('file:///foo'))
239
            self.assertEqual(('file:///', ''), split('file:///'))
240
241
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo'))
242
        self.assertEqual(('http://host/path/to', 'foo'), split('http://host/path/to/foo/'))
243
        self.assertEqual(('http://host/path/to/foo', ''),
244
            split('http://host/path/to/foo/', exclude_trailing_slash=False))
245
        self.assertEqual(('http://host/', 'path'), split('http://host/path'))
246
        self.assertEqual(('http://host/', ''), split('http://host/'))
247
        self.assertEqual(('http://host', ''), split('http://host'))
248
        self.assertEqual(('http:///nohost', 'path'), split('http:///nohost/path'))
249
250
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
251
            split('random+scheme://user:pass@ahost:port/path'))
252
        self.assertEqual(('random+scheme://user:pass@ahost:port/', 'path'),
253
            split('random+scheme://user:pass@ahost:port/path/'))
254
        self.assertEqual(('random+scheme://user:pass@ahost:port/', ''),
255
            split('random+scheme://user:pass@ahost:port/'))
256
257
        # relative paths
258
        self.assertEqual(('path/to', 'foo'), split('path/to/foo'))
259
        self.assertEqual(('path/to', 'foo'), split('path/to/foo/'))
260
        self.assertEqual(('path/to/foo', ''),
261
            split('path/to/foo/', exclude_trailing_slash=False))
262
        self.assertEqual(('path/..', 'foo'), split('path/../foo'))
263
        self.assertEqual(('../path', 'foo'), split('../path/foo'))
264
1685.1.48 by John Arbash Meinel
Updated strip_trailing_slash to support lots more url stuff, added tests
265
    def test_strip_trailing_slash(self):
266
        sts = urlutils.strip_trailing_slash
267
        if sys.platform == 'win32':
268
            self.assertEqual('file:///C|/', sts('file:///C|/'))
269
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo'))
270
            self.assertEqual('file:///C|/foo', sts('file:///C|/foo/'))
271
        else:
272
            self.assertEqual('file:///', sts('file:///'))
273
            self.assertEqual('file:///foo', sts('file:///foo'))
274
            self.assertEqual('file:///foo', sts('file:///foo/'))
275
276
        self.assertEqual('http://host/', sts('http://host/'))
277
        self.assertEqual('http://host/foo', sts('http://host/foo'))
278
        self.assertEqual('http://host/foo', sts('http://host/foo/'))
279
280
        # No need to fail just because the slash is missing
281
        self.assertEqual('http://host', sts('http://host'))
282
        # TODO: jam 20060502 Should this raise InvalidURL?
283
        self.assertEqual('file://', sts('file://'))
284
285
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
286
            sts('random+scheme://user:pass@ahost:port/path'))
287
        self.assertEqual('random+scheme://user:pass@ahost:port/path',
288
            sts('random+scheme://user:pass@ahost:port/path/'))
289
        self.assertEqual('random+scheme://user:pass@ahost:port/',
290
            sts('random+scheme://user:pass@ahost:port/'))
291
292
        # Make sure relative paths work too
293
        self.assertEqual('path/to/foo', sts('path/to/foo'))
294
        self.assertEqual('path/to/foo', sts('path/to/foo/'))
295
        self.assertEqual('../to/foo', sts('../to/foo/'))
296
        self.assertEqual('path/../foo', sts('path/../foo/'))
297
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
298
    def test_unescape_for_display(self):
299
        # Test that URLs are converted to nice unicode strings for display
300
        disp = urlutils.unescape_for_display
301
        eq = self.assertEqual
302
        eq('http://foo', disp('http://foo'))
303
        if sys.platform == 'win32':
304
            eq('C:/foo/path', disp('file:///C|foo/path'))
305
        else:
306
            eq('/foo/path', disp('file:///foo/path'))
307
308
        eq('http://foo/%2Fbaz', disp('http://foo/%2Fbaz'))
309
        eq(u'http://host/r\xe4ksm\xf6rg\xe5s', disp('http://host/r%C3%A4ksm%C3%B6rg%C3%A5s'))
310
311
        # Make sure special escaped characters stay escaped
312
        eq(u'http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23',
313
            disp('http://host/%3B%2F%3F%3A%40%26%3D%2B%24%2C%23'))
314
315
        # Can we handle sections that don't have utf-8 encoding?
316
        eq(u'http://host/%EE%EE%EE/r\xe4ksm\xf6rg\xe5s',
317
            disp('http://host/%EE%EE%EE/r%C3%A4ksm%C3%B6rg%C3%A5s'))
318
319
    def test_escape(self):
320
        self.assertEqual('%25', urlutils.escape('%'))
321
        self.assertEqual('%C3%A5', urlutils.escape(u'\xe5'))
322
323
    def test_unescape(self):
324
        self.assertEqual('%', urlutils.unescape('%25'))
325
        self.assertEqual(u'\xe5', urlutils.unescape('%C3%A5'))
326
327
        self.assertRaises(InvalidURL, urlutils.unescape, u'\xe5')
328
        self.assertRaises(InvalidURL, urlutils.unescape, '\xe5')
329
        self.assertRaises(InvalidURL, urlutils.unescape, '%E5')
330
331
    def test_escape_unescape(self):
332
        self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5')))
333
        self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
334