##// END OF EJS Templates
tests: fix deprecation warning in test-url.py
Augie Fackler -
r37974:d088810c default
parent child Browse files
Show More
@@ -1,423 +1,424 b''
1 1 # coding=utf-8
2 2 from __future__ import absolute_import, print_function
3 3
4 4 import doctest
5 5 import os
6 6
7 7 def check(a, b):
8 8 if a != b:
9 9 print((a, b))
10 10
11 11 def cert(cn):
12 12 return {'subject': ((('commonName', cn),),)}
13 13
14 14 from mercurial import (
15 15 sslutil,
16 16 )
17 17
18 18 _verifycert = sslutil._verifycert
19 19 # Test non-wildcard certificates
20 20 check(_verifycert(cert('example.com'), 'example.com'),
21 21 None)
22 22 check(_verifycert(cert('example.com'), 'www.example.com'),
23 23 b'certificate is for example.com')
24 24 check(_verifycert(cert('www.example.com'), 'example.com'),
25 25 b'certificate is for www.example.com')
26 26
27 27 # Test wildcard certificates
28 28 check(_verifycert(cert('*.example.com'), 'www.example.com'),
29 29 None)
30 30 check(_verifycert(cert('*.example.com'), 'example.com'),
31 31 b'certificate is for *.example.com')
32 32 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
33 33 b'certificate is for *.example.com')
34 34
35 35 # Test subjectAltName
36 36 san_cert = {'subject': ((('commonName', 'example.com'),),),
37 37 'subjectAltName': (('DNS', '*.example.net'),
38 38 ('DNS', 'example.net'))}
39 39 check(_verifycert(san_cert, 'example.net'),
40 40 None)
41 41 check(_verifycert(san_cert, 'foo.example.net'),
42 42 None)
43 43 # no fallback to subject commonName when subjectAltName has DNS
44 44 check(_verifycert(san_cert, 'example.com'),
45 45 b'certificate is for *.example.net, example.net')
46 46 # fallback to subject commonName when no DNS in subjectAltName
47 47 san_cert = {'subject': ((('commonName', 'example.com'),),),
48 48 'subjectAltName': (('IP Address', '8.8.8.8'),)}
49 49 check(_verifycert(san_cert, 'example.com'), None)
50 50
51 51 # Avoid some pitfalls
52 52 check(_verifycert(cert('*.foo'), 'foo'),
53 53 b'certificate is for *.foo')
54 54 check(_verifycert(cert('*o'), 'foo'), None)
55 55
56 56 check(_verifycert({'subject': ()},
57 57 'example.com'),
58 58 b'no commonName or subjectAltName found in certificate')
59 59 check(_verifycert(None, 'example.com'),
60 60 b'no certificate received')
61 61
62 62 # Unicode (IDN) certname isn't supported
63 63 check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
64 64 b'IDN in certificate not supported')
65 65
66 66 # The following tests are from CPython's test_ssl.py.
67 67 check(_verifycert(cert('example.com'), 'example.com'), None)
68 68 check(_verifycert(cert('example.com'), 'ExAmple.cOm'), None)
69 69 check(_verifycert(cert('example.com'), 'www.example.com'),
70 70 b'certificate is for example.com')
71 71 check(_verifycert(cert('example.com'), '.example.com'),
72 72 b'certificate is for example.com')
73 73 check(_verifycert(cert('example.com'), 'example.org'),
74 74 b'certificate is for example.com')
75 75 check(_verifycert(cert('example.com'), 'exampleXcom'),
76 76 b'certificate is for example.com')
77 77 check(_verifycert(cert('*.a.com'), 'foo.a.com'), None)
78 78 check(_verifycert(cert('*.a.com'), 'bar.foo.a.com'),
79 79 b'certificate is for *.a.com')
80 80 check(_verifycert(cert('*.a.com'), 'a.com'),
81 81 b'certificate is for *.a.com')
82 82 check(_verifycert(cert('*.a.com'), 'Xa.com'),
83 83 b'certificate is for *.a.com')
84 84 check(_verifycert(cert('*.a.com'), '.a.com'),
85 85 b'certificate is for *.a.com')
86 86
87 87 # only match one left-most wildcard
88 88 check(_verifycert(cert('f*.com'), 'foo.com'), None)
89 89 check(_verifycert(cert('f*.com'), 'f.com'), None)
90 90 check(_verifycert(cert('f*.com'), 'bar.com'),
91 91 b'certificate is for f*.com')
92 92 check(_verifycert(cert('f*.com'), 'foo.a.com'),
93 93 b'certificate is for f*.com')
94 94 check(_verifycert(cert('f*.com'), 'bar.foo.com'),
95 95 b'certificate is for f*.com')
96 96
97 97 # NULL bytes are bad, CVE-2013-4073
98 98 check(_verifycert(cert('null.python.org\x00example.org'),
99 99 'null.python.org\x00example.org'), None)
100 100 check(_verifycert(cert('null.python.org\x00example.org'),
101 101 'example.org'),
102 102 b'certificate is for null.python.org\x00example.org')
103 103 check(_verifycert(cert('null.python.org\x00example.org'),
104 104 'null.python.org'),
105 105 b'certificate is for null.python.org\x00example.org')
106 106
107 107 # error cases with wildcards
108 108 check(_verifycert(cert('*.*.a.com'), 'bar.foo.a.com'),
109 109 b'certificate is for *.*.a.com')
110 110 check(_verifycert(cert('*.*.a.com'), 'a.com'),
111 111 b'certificate is for *.*.a.com')
112 112 check(_verifycert(cert('*.*.a.com'), 'Xa.com'),
113 113 b'certificate is for *.*.a.com')
114 114 check(_verifycert(cert('*.*.a.com'), '.a.com'),
115 115 b'certificate is for *.*.a.com')
116 116
117 117 check(_verifycert(cert('a.*.com'), 'a.foo.com'),
118 118 b'certificate is for a.*.com')
119 119 check(_verifycert(cert('a.*.com'), 'a..com'),
120 120 b'certificate is for a.*.com')
121 121 check(_verifycert(cert('a.*.com'), 'a.com'),
122 122 b'certificate is for a.*.com')
123 123
124 124 # wildcard doesn't match IDNA prefix 'xn--'
125 125 idna = u'pΓΌthon.python.org'.encode('idna').decode('ascii')
126 126 check(_verifycert(cert(idna), idna), None)
127 127 check(_verifycert(cert('x*.python.org'), idna),
128 128 b'certificate is for x*.python.org')
129 129 check(_verifycert(cert('xn--p*.python.org'), idna),
130 130 b'certificate is for xn--p*.python.org')
131 131
132 132 # wildcard in first fragment and IDNA A-labels in sequent fragments
133 133 # are supported.
134 134 idna = u'www*.pythΓΆn.org'.encode('idna').decode('ascii')
135 135 check(_verifycert(cert(idna),
136 136 u'www.pythΓΆn.org'.encode('idna').decode('ascii')),
137 137 None)
138 138 check(_verifycert(cert(idna),
139 139 u'www1.pythΓΆn.org'.encode('idna').decode('ascii')),
140 140 None)
141 141 check(_verifycert(cert(idna),
142 142 u'ftp.pythΓΆn.org'.encode('idna').decode('ascii')),
143 143 b'certificate is for www*.xn--pythn-mua.org')
144 144 check(_verifycert(cert(idna),
145 145 u'pythΓΆn.org'.encode('idna').decode('ascii')),
146 146 b'certificate is for www*.xn--pythn-mua.org')
147 147
148 148 c = {
149 149 'notAfter': 'Jun 26 21:41:46 2011 GMT',
150 150 'subject': (((u'commonName', u'linuxfrz.org'),),),
151 151 'subjectAltName': (
152 152 ('DNS', 'linuxfr.org'),
153 153 ('DNS', 'linuxfr.com'),
154 154 ('othername', '<unsupported>'),
155 155 )
156 156 }
157 157 check(_verifycert(c, 'linuxfr.org'), None)
158 158 check(_verifycert(c, 'linuxfr.com'), None)
159 159 # Not a "DNS" entry
160 160 check(_verifycert(c, '<unsupported>'),
161 161 b'certificate is for linuxfr.org, linuxfr.com')
162 162 # When there is a subjectAltName, commonName isn't used
163 163 check(_verifycert(c, 'linuxfrz.org'),
164 164 b'certificate is for linuxfr.org, linuxfr.com')
165 165
166 166 # A pristine real-world example
167 167 c = {
168 168 'notAfter': 'Dec 18 23:59:59 2011 GMT',
169 169 'subject': (
170 170 ((u'countryName', u'US'),),
171 171 ((u'stateOrProvinceName', u'California'),),
172 172 ((u'localityName', u'Mountain View'),),
173 173 ((u'organizationName', u'Google Inc'),),
174 174 ((u'commonName', u'mail.google.com'),),
175 175 ),
176 176 }
177 177 check(_verifycert(c, 'mail.google.com'), None)
178 178 check(_verifycert(c, 'gmail.com'), b'certificate is for mail.google.com')
179 179
180 180 # Only commonName is considered
181 181 check(_verifycert(c, 'California'), b'certificate is for mail.google.com')
182 182
183 183 # Neither commonName nor subjectAltName
184 184 c = {
185 185 'notAfter': 'Dec 18 23:59:59 2011 GMT',
186 186 'subject': (
187 187 ((u'countryName', u'US'),),
188 188 ((u'stateOrProvinceName', u'California'),),
189 189 ((u'localityName', u'Mountain View'),),
190 190 ((u'organizationName', u'Google Inc'),),
191 191 ),
192 192 }
193 193 check(_verifycert(c, 'mail.google.com'),
194 194 b'no commonName or subjectAltName found in certificate')
195 195
196 196 # No DNS entry in subjectAltName but a commonName
197 197 c = {
198 198 'notAfter': 'Dec 18 23:59:59 2099 GMT',
199 199 'subject': (
200 200 ((u'countryName', u'US'),),
201 201 ((u'stateOrProvinceName', u'California'),),
202 202 ((u'localityName', u'Mountain View'),),
203 203 ((u'commonName', u'mail.google.com'),),
204 204 ),
205 205 'subjectAltName': (('othername', 'blabla'),),
206 206 }
207 207 check(_verifycert(c, 'mail.google.com'), None)
208 208
209 209 # No DNS entry subjectAltName and no commonName
210 210 c = {
211 211 'notAfter': 'Dec 18 23:59:59 2099 GMT',
212 212 'subject': (
213 213 ((u'countryName', u'US'),),
214 214 ((u'stateOrProvinceName', u'California'),),
215 215 ((u'localityName', u'Mountain View'),),
216 216 ((u'organizationName', u'Google Inc'),),
217 217 ),
218 218 'subjectAltName': (('othername', 'blabla'),),
219 219 }
220 220 check(_verifycert(c, 'google.com'),
221 221 b'no commonName or subjectAltName found in certificate')
222 222
223 223 # Empty cert / no cert
224 224 check(_verifycert(None, 'example.com'), b'no certificate received')
225 225 check(_verifycert({}, 'example.com'), b'no certificate received')
226 226
227 227 # avoid denials of service by refusing more than one
228 228 # wildcard per fragment.
229 229 check(_verifycert({'subject': (((u'commonName', u'a*b.com'),),)},
230 230 'axxb.com'), None)
231 231 check(_verifycert({'subject': (((u'commonName', u'a*b.co*'),),)},
232 232 'axxb.com'), b'certificate is for a*b.co*')
233 233 check(_verifycert({'subject': (((u'commonName', u'a*b*.com'),),)},
234 234 'axxbxxc.com'),
235 235 b'too many wildcards in certificate DNS name: a*b*.com')
236 236
237 237 def test_url():
238 238 """
239 239 >>> from mercurial import error, pycompat
240 >>> from mercurial.util import forcebytestr, url
240 >>> from mercurial.util import url
241 >>> from mercurial.utils.stringutil import forcebytestr
241 242
242 243 This tests for edge cases in url.URL's parsing algorithm. Most of
243 244 these aren't useful for documentation purposes, so they aren't
244 245 part of the class's doc tests.
245 246
246 247 Query strings and fragments:
247 248
248 249 >>> url(b'http://host/a?b#c')
249 250 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
250 251 >>> url(b'http://host/a?')
251 252 <url scheme: 'http', host: 'host', path: 'a'>
252 253 >>> url(b'http://host/a#b#c')
253 254 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b#c'>
254 255 >>> url(b'http://host/a#b?c')
255 256 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b?c'>
256 257 >>> url(b'http://host/?a#b')
257 258 <url scheme: 'http', host: 'host', path: '', query: 'a', fragment: 'b'>
258 259 >>> url(b'http://host/?a#b', parsequery=False)
259 260 <url scheme: 'http', host: 'host', path: '?a', fragment: 'b'>
260 261 >>> url(b'http://host/?a#b', parsefragment=False)
261 262 <url scheme: 'http', host: 'host', path: '', query: 'a#b'>
262 263 >>> url(b'http://host/?a#b', parsequery=False, parsefragment=False)
263 264 <url scheme: 'http', host: 'host', path: '?a#b'>
264 265
265 266 IPv6 addresses:
266 267
267 268 >>> url(b'ldap://[2001:db8::7]/c=GB?objectClass?one')
268 269 <url scheme: 'ldap', host: '[2001:db8::7]', path: 'c=GB',
269 270 query: 'objectClass?one'>
270 271 >>> url(b'ldap://joe:xxx@[2001:db8::7]:80/c=GB?objectClass?one')
271 272 <url scheme: 'ldap', user: 'joe', passwd: 'xxx', host: '[2001:db8::7]',
272 273 port: '80', path: 'c=GB', query: 'objectClass?one'>
273 274
274 275 Missing scheme, host, etc.:
275 276
276 277 >>> url(b'://192.0.2.16:80/')
277 278 <url path: '://192.0.2.16:80/'>
278 279 >>> url(b'https://mercurial-scm.org')
279 280 <url scheme: 'https', host: 'mercurial-scm.org'>
280 281 >>> url(b'/foo')
281 282 <url path: '/foo'>
282 283 >>> url(b'bundle:/foo')
283 284 <url scheme: 'bundle', path: '/foo'>
284 285 >>> url(b'a?b#c')
285 286 <url path: 'a?b', fragment: 'c'>
286 287 >>> url(b'http://x.com?arg=/foo')
287 288 <url scheme: 'http', host: 'x.com', query: 'arg=/foo'>
288 289 >>> url(b'http://joe:xxx@/foo')
289 290 <url scheme: 'http', user: 'joe', passwd: 'xxx', path: 'foo'>
290 291
291 292 Just a scheme and a path:
292 293
293 294 >>> url(b'mailto:John.Doe@example.com')
294 295 <url scheme: 'mailto', path: 'John.Doe@example.com'>
295 296 >>> url(b'a:b:c:d')
296 297 <url path: 'a:b:c:d'>
297 298 >>> url(b'aa:bb:cc:dd')
298 299 <url scheme: 'aa', path: 'bb:cc:dd'>
299 300
300 301 SSH examples:
301 302
302 303 >>> url(b'ssh://joe@host//home/joe')
303 304 <url scheme: 'ssh', user: 'joe', host: 'host', path: '/home/joe'>
304 305 >>> url(b'ssh://joe:xxx@host/src')
305 306 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', path: 'src'>
306 307 >>> url(b'ssh://joe:xxx@host')
307 308 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host'>
308 309 >>> url(b'ssh://joe@host')
309 310 <url scheme: 'ssh', user: 'joe', host: 'host'>
310 311 >>> url(b'ssh://host')
311 312 <url scheme: 'ssh', host: 'host'>
312 313 >>> url(b'ssh://')
313 314 <url scheme: 'ssh'>
314 315 >>> url(b'ssh:')
315 316 <url scheme: 'ssh'>
316 317
317 318 Non-numeric port:
318 319
319 320 >>> url(b'http://example.com:dd')
320 321 <url scheme: 'http', host: 'example.com', port: 'dd'>
321 322 >>> url(b'ssh://joe:xxx@host:ssh/foo')
322 323 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', port: 'ssh',
323 324 path: 'foo'>
324 325
325 326 Bad authentication credentials:
326 327
327 328 >>> url(b'http://joe@joeville:123@4:@host/a?b#c')
328 329 <url scheme: 'http', user: 'joe@joeville', passwd: '123@4:',
329 330 host: 'host', path: 'a', query: 'b', fragment: 'c'>
330 331 >>> url(b'http://!*#?/@!*#?/:@host/a?b#c')
331 332 <url scheme: 'http', host: '!*', fragment: '?/@!*#?/:@host/a?b#c'>
332 333 >>> url(b'http://!*#?@!*#?:@host/a?b#c')
333 334 <url scheme: 'http', host: '!*', fragment: '?@!*#?:@host/a?b#c'>
334 335 >>> url(b'http://!*@:!*@@host/a?b#c')
335 336 <url scheme: 'http', user: '!*@', passwd: '!*@', host: 'host',
336 337 path: 'a', query: 'b', fragment: 'c'>
337 338
338 339 File paths:
339 340
340 341 >>> url(b'a/b/c/d.g.f')
341 342 <url path: 'a/b/c/d.g.f'>
342 343 >>> url(b'/x///z/y/')
343 344 <url path: '/x///z/y/'>
344 345 >>> url(b'/foo:bar')
345 346 <url path: '/foo:bar'>
346 347 >>> url(b'\\\\foo:bar')
347 348 <url path: '\\\\foo:bar'>
348 349 >>> url(b'./foo:bar')
349 350 <url path: './foo:bar'>
350 351
351 352 Non-localhost file URL:
352 353
353 354 >>> try:
354 355 ... u = url(b'file://mercurial-scm.org/foo')
355 356 ... except error.Abort as e:
356 357 ... forcebytestr(e)
357 358 'file:// URLs can only refer to localhost'
358 359
359 360 Empty URL:
360 361
361 362 >>> u = url(b'')
362 363 >>> u
363 364 <url path: ''>
364 365 >>> str(u)
365 366 ''
366 367
367 368 Empty path with query string:
368 369
369 370 >>> str(url(b'http://foo/?bar'))
370 371 'http://foo/?bar'
371 372
372 373 Invalid path:
373 374
374 375 >>> u = url(b'http://foo/bar')
375 376 >>> u.path = b'bar'
376 377 >>> str(u)
377 378 'http://foo/bar'
378 379
379 380 >>> u = url(b'file:/foo/bar/baz')
380 381 >>> u
381 382 <url scheme: 'file', path: '/foo/bar/baz'>
382 383 >>> str(u)
383 384 'file:///foo/bar/baz'
384 385 >>> pycompat.bytestr(u.localpath())
385 386 '/foo/bar/baz'
386 387
387 388 >>> u = url(b'file:///foo/bar/baz')
388 389 >>> u
389 390 <url scheme: 'file', path: '/foo/bar/baz'>
390 391 >>> str(u)
391 392 'file:///foo/bar/baz'
392 393 >>> pycompat.bytestr(u.localpath())
393 394 '/foo/bar/baz'
394 395
395 396 >>> u = url(b'file:///f:oo/bar/baz')
396 397 >>> u
397 398 <url scheme: 'file', path: 'f:oo/bar/baz'>
398 399 >>> str(u)
399 400 'file:///f:oo/bar/baz'
400 401 >>> pycompat.bytestr(u.localpath())
401 402 'f:oo/bar/baz'
402 403
403 404 >>> u = url(b'file://localhost/f:oo/bar/baz')
404 405 >>> u
405 406 <url scheme: 'file', host: 'localhost', path: 'f:oo/bar/baz'>
406 407 >>> str(u)
407 408 'file://localhost/f:oo/bar/baz'
408 409 >>> pycompat.bytestr(u.localpath())
409 410 'f:oo/bar/baz'
410 411
411 412 >>> u = url(b'file:foo/bar/baz')
412 413 >>> u
413 414 <url scheme: 'file', path: 'foo/bar/baz'>
414 415 >>> str(u)
415 416 'file:foo/bar/baz'
416 417 >>> pycompat.bytestr(u.localpath())
417 418 'foo/bar/baz'
418 419 """
419 420
420 421 if 'TERM' in os.environ:
421 422 del os.environ['TERM']
422 423
423 424 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
General Comments 0
You need to be logged in to leave comments. Login now