gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / cssutils / tests / test_util.py @ 475
History | View | Annotate | Download (17.6 KB)
1 |
# -*- coding: utf-8 -*- |
---|---|
2 |
"""Testcases for cssutils.util"""
|
3 |
from __future__ import with_statement |
4 |
|
5 |
import cgi |
6 |
from email import message_from_string, message_from_file |
7 |
import StringIO |
8 |
import sys |
9 |
import urllib2 |
10 |
import xml.dom |
11 |
|
12 |
try:
|
13 |
import mock |
14 |
except ImportError: |
15 |
mock = None
|
16 |
print "install mock library to run all tests" |
17 |
|
18 |
import basetest |
19 |
import encutils |
20 |
|
21 |
from cssutils.util import Base, ListSeq, _readUrl, _defaultFetcher |
22 |
|
23 |
class ListSeqTestCase(basetest.BaseTestCase): |
24 |
|
25 |
def test_all(self): |
26 |
"util.ListSeq"
|
27 |
ls = ListSeq() |
28 |
self.assertEqual(0, len(ls)) |
29 |
# append()
|
30 |
self.assertRaises(NotImplementedError, ls.append, 1) |
31 |
# set
|
32 |
self.assertRaises(NotImplementedError, ls.__setitem__, 0, 1) |
33 |
|
34 |
# hack:
|
35 |
ls.seq.append(1)
|
36 |
ls.seq.append(2)
|
37 |
|
38 |
# len
|
39 |
self.assertEqual(2, len(ls)) |
40 |
# __contains__
|
41 |
self.assertEqual(True, 1 in ls) |
42 |
# get
|
43 |
self.assertEqual(1, ls[0]) |
44 |
self.assertEqual(2, ls[1]) |
45 |
# del
|
46 |
del ls[0] |
47 |
self.assertEqual(1, len(ls)) |
48 |
self.assertEqual(False, 1 in ls) |
49 |
# for in
|
50 |
for x in ls: |
51 |
self.assertEqual(2, x) |
52 |
|
53 |
|
54 |
class BaseTestCase(basetest.BaseTestCase): |
55 |
|
56 |
def test_normalize(self): |
57 |
"Base._normalize()"
|
58 |
b = Base() |
59 |
tests = {u'abcdefg ABCDEFG äöü߀ AÖÜ': u'abcdefg abcdefg äöü߀ aöü', |
60 |
ur'\ga\Ga\\\ ': ur'gaga\ ', |
61 |
ur'0123456789': u'0123456789', |
62 |
# unicode escape seqs should have been done by
|
63 |
# the tokenizer...
|
64 |
} |
65 |
for test, exp in tests.items(): |
66 |
self.assertEqual(b._normalize(test), exp)
|
67 |
# static too
|
68 |
self.assertEqual(Base._normalize(test), exp)
|
69 |
|
70 |
def test_tokenupto(self): |
71 |
"Base._tokensupto2()"
|
72 |
|
73 |
# tests nested blocks of {} [] or ()
|
74 |
b = Base() |
75 |
|
76 |
tests = [ |
77 |
('default', u'a[{1}]({2}) { } NOT', u'a[{1}]({2}) { }', False), |
78 |
('default', u'a[{1}]({2}) { } NOT', u'a[{1}]func({2}) { }', True), |
79 |
('blockstartonly', u'a[{1}]({2}) { NOT', u'a[{1}]({2}) {', False), |
80 |
('blockstartonly', u'a[{1}]({2}) { NOT', u'a[{1}]func({2}) {', True), |
81 |
('propertynameendonly', u'a[(2)1] { }2 : a;', u'a[(2)1] { }2 :', False), |
82 |
('propertynameendonly', u'a[(2)1] { }2 : a;', u'a[func(2)1] { }2 :', True), |
83 |
('propertyvalueendonly', u'a{;{;}[;](;)}[;{;}[;](;)](;{;}[;](;)) 1; NOT', |
84 |
u'a{;{;}[;](;)}[;{;}[;](;)](;{;}[;](;)) 1;', False), |
85 |
('propertyvalueendonly', u'a{;{;}[;](;)}[;{;}[;](;)](;{;}[;](;)) 1; NOT', |
86 |
u'a{;{;}[;]func(;)}[;{;}[;]func(;)]func(;{;}[;]func(;)) 1;', True), |
87 |
('funcendonly', u'a{[1]}([3])[{[1]}[2]([3])]) NOT', |
88 |
u'a{[1]}([3])[{[1]}[2]([3])])', False), |
89 |
('funcendonly', u'a{[1]}([3])[{[1]}[2]([3])]) NOT', |
90 |
u'a{[1]}func([3])[{[1]}[2]func([3])])', True), |
91 |
('selectorattendonly', u'[a[()]{()}([()]{()}())] NOT', |
92 |
u'[a[()]{()}([()]{()}())]', False), |
93 |
('selectorattendonly', u'[a[()]{()}([()]{()}())] NOT', |
94 |
u'[a[func()]{func()}func([func()]{func()}func())]', True), |
95 |
# issue 50
|
96 |
('withstarttoken [', u'a];x', u'[a];', False) |
97 |
] |
98 |
|
99 |
for typ, values, exp, paransasfunc in tests: |
100 |
|
101 |
def maketokens(valuelist): |
102 |
# returns list of tuples
|
103 |
return [('TYPE', v, 0, 0) for v in valuelist] |
104 |
|
105 |
tokens = maketokens(list(values))
|
106 |
if paransasfunc:
|
107 |
for i, t in enumerate(tokens): |
108 |
if u'(' == t[1]: |
109 |
tokens[i] = ('FUNCTION', u'func(', t[2], t[3]) |
110 |
|
111 |
if 'default' == typ: |
112 |
restokens = b._tokensupto2(tokens) |
113 |
elif 'blockstartonly' == typ: |
114 |
restokens = b._tokensupto2( |
115 |
tokens, blockstartonly=True)
|
116 |
elif 'propertynameendonly' == typ: |
117 |
restokens = b._tokensupto2( |
118 |
tokens, propertynameendonly=True)
|
119 |
elif 'propertyvalueendonly' == typ: |
120 |
restokens = b._tokensupto2( |
121 |
tokens, propertyvalueendonly=True)
|
122 |
elif 'funcendonly' == typ: |
123 |
restokens = b._tokensupto2( |
124 |
tokens, funcendonly=True)
|
125 |
elif 'selectorattendonly' == typ: |
126 |
restokens = b._tokensupto2( |
127 |
tokens, selectorattendonly=True)
|
128 |
elif 'withstarttoken [' == typ: |
129 |
restokens = b._tokensupto2(tokens, ('CHAR', '[', 0, 0)) |
130 |
|
131 |
res = u''.join([t[1] for t in restokens]) |
132 |
self.assertEqual(exp, res)
|
133 |
|
134 |
|
135 |
class _readUrl_TestCase(basetest.BaseTestCase): |
136 |
"""needs mock"""
|
137 |
|
138 |
def test_readUrl(self): |
139 |
"""util._readUrl()"""
|
140 |
# for additional tests see test_parse.py
|
141 |
url = 'http://example.com/test.css'
|
142 |
|
143 |
def make_fetcher(r): |
144 |
# normally r == encoding, content
|
145 |
def fetcher(url): |
146 |
return r
|
147 |
return fetcher
|
148 |
|
149 |
tests = { |
150 |
# defaultFetcher returns: readUrl returns
|
151 |
None: (None, None, None), |
152 |
(None, ''): ('utf-8', 5, u''), |
153 |
(None, u'€'.encode('utf-8')): ('utf-8', 5, u'€'), |
154 |
('utf-8', u'€'.encode('utf-8')): ('utf-8', 1, u'€'), |
155 |
('ISO-8859-1', u'ä'.encode('iso-8859-1')): ('ISO-8859-1', 1, u'ä'), |
156 |
('ASCII', u'a'.encode('ascii')): ('ASCII', 1, u'a') |
157 |
} |
158 |
|
159 |
for r, exp in tests.items(): |
160 |
self.assertEqual(_readUrl(url, fetcher=make_fetcher(r)), exp)
|
161 |
|
162 |
tests = { |
163 |
# (overrideEncoding, parentEncoding, (httpencoding, content)):
|
164 |
# readUrl returns
|
165 |
|
166 |
# ===== 0. OVERRIDE WINS =====
|
167 |
# override + parent + http
|
168 |
('latin1', 'ascii', ('utf-16', u''.encode())): ('latin1', 0, u''), |
169 |
('latin1', 'ascii', ('utf-16', u'123'.encode())): ('latin1', 0, u'123'), |
170 |
('latin1', 'ascii', ('utf-16', u'ä'.encode('iso-8859-1'))): |
171 |
('latin1', 0, u'ä'), |
172 |
('latin1', 'ascii', ('utf-16', u'a'.encode('ascii'))): |
173 |
('latin1',0, u'a'), |
174 |
# + @charset
|
175 |
('latin1', 'ascii', ('utf-16', u'@charset "ascii";'.encode())): |
176 |
('latin1', 0, u'@charset "latin1";'), |
177 |
('latin1', 'ascii', ('utf-16', u'@charset "utf-8";ä'.encode('latin1'))): |
178 |
('latin1', 0, u'@charset "latin1";ä'), |
179 |
('latin1', 'ascii', ('utf-16', u'@charset "utf-8";ä'.encode('utf-8'))): |
180 |
('latin1', 0, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
181 |
|
182 |
# override only
|
183 |
('latin1', None, None): (None, None, None), |
184 |
('latin1', None, (None, u''.encode())): ('latin1', 0, u''), |
185 |
('latin1', None, (None, u'123'.encode())): ('latin1', 0, u'123'), |
186 |
('latin1', None, (None, u'ä'.encode('iso-8859-1'))): |
187 |
('latin1', 0, u'ä'), |
188 |
('latin1', None, (None, u'a'.encode('ascii'))): |
189 |
('latin1', 0, u'a'), |
190 |
# + @charset
|
191 |
('latin1', None, (None, u'@charset "ascii";'.encode())): |
192 |
('latin1', 0, u'@charset "latin1";'), |
193 |
('latin1', None, (None, u'@charset "utf-8";ä'.encode('latin1'))): |
194 |
('latin1', 0, u'@charset "latin1";ä'), |
195 |
('latin1', None, (None, u'@charset "utf-8";ä'.encode('utf-8'))): |
196 |
('latin1', 0, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
197 |
|
198 |
# override + parent
|
199 |
('latin1', 'ascii', None): (None, None, None), |
200 |
('latin1', 'ascii', (None, u''.encode())): ('latin1', 0, u''), |
201 |
('latin1', 'ascii', (None, u'123'.encode())): ('latin1', 0, u'123'), |
202 |
('latin1', 'ascii', (None, u'ä'.encode('iso-8859-1'))): |
203 |
('latin1', 0, u'ä'), |
204 |
('latin1', 'ascii', (None, u'a'.encode('ascii'))): |
205 |
('latin1', 0, u'a'), |
206 |
# + @charset
|
207 |
('latin1', 'ascii', (None, u'@charset "ascii";'.encode())): |
208 |
('latin1', 0, u'@charset "latin1";'), |
209 |
('latin1', 'ascii', (None, u'@charset "utf-8";ä'.encode('latin1'))): |
210 |
('latin1', 0, u'@charset "latin1";ä'), |
211 |
('latin1', 'ascii', (None, u'@charset "utf-8";ä'.encode('utf-8'))): |
212 |
('latin1', 0, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
213 |
|
214 |
# override + http
|
215 |
('latin1', None, ('utf-16', u''.encode())): ('latin1', 0, u''), |
216 |
('latin1', None, ('utf-16', u'123'.encode())): ('latin1', 0, u'123'), |
217 |
('latin1', None, ('utf-16', u'ä'.encode('iso-8859-1'))): |
218 |
('latin1', 0, u'ä'), |
219 |
('latin1', None, ('utf-16', u'a'.encode('ascii'))): |
220 |
('latin1', 0, u'a'), |
221 |
# + @charset
|
222 |
('latin1', None, ('utf-16', u'@charset "ascii";'.encode())): |
223 |
('latin1', 0, u'@charset "latin1";'), |
224 |
('latin1', None, ('utf-16', u'@charset "utf-8";ä'.encode('latin1'))): |
225 |
('latin1', 0, u'@charset "latin1";ä'), |
226 |
('latin1', None, ('utf-16', u'@charset "utf-8";ä'.encode('utf-8'))): |
227 |
('latin1', 0, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
228 |
|
229 |
# override ü @charset
|
230 |
('latin1', None, (None, u'@charset "ascii";'.encode())): |
231 |
('latin1', 0, u'@charset "latin1";'), |
232 |
('latin1', None, (None, u'@charset "utf-8";ä'.encode('latin1'))): |
233 |
('latin1', 0, u'@charset "latin1";ä'), |
234 |
('latin1', None, (None, u'@charset "utf-8";ä'.encode('utf-8'))): |
235 |
('latin1', 0, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
236 |
|
237 |
|
238 |
# ===== 1. HTTP WINS =====
|
239 |
(None, 'ascii', ('latin1', u''.encode())): ('latin1', 1, u''), |
240 |
(None, 'ascii', ('latin1', u'123'.encode())): ('latin1', 1, u'123'), |
241 |
(None, 'ascii', ('latin1', u'ä'.encode('iso-8859-1'))): |
242 |
('latin1', 1, u'ä'), |
243 |
(None, 'ascii', ('latin1', u'a'.encode('ascii'))): |
244 |
('latin1', 1, u'a'), |
245 |
# + @charset
|
246 |
(None, 'ascii', ('latin1', u'@charset "ascii";'.encode())): |
247 |
('latin1', 1, u'@charset "latin1";'), |
248 |
(None, 'ascii', ('latin1', u'@charset "utf-8";ä'.encode('latin1'))): |
249 |
('latin1', 1, u'@charset "latin1";ä'), |
250 |
(None, 'ascii', ('latin1', u'@charset "utf-8";ä'.encode('utf-8'))): |
251 |
('latin1', 1, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
252 |
|
253 |
|
254 |
# ===== 2. @charset WINS =====
|
255 |
(None, 'ascii', (None, u'@charset "latin1";'.encode())): |
256 |
('latin1', 2, u'@charset "latin1";'), |
257 |
(None, 'ascii', (None, u'@charset "latin1";ä'.encode('latin1'))): |
258 |
('latin1', 2, u'@charset "latin1";ä'), |
259 |
(None, 'ascii', (None, u'@charset "latin1";ä'.encode('utf-8'))): |
260 |
('latin1', 2, u'@charset "latin1";\xc3\xa4'), # read as latin1! |
261 |
|
262 |
# ===== 2. BOM WINS =====
|
263 |
(None, 'ascii', (None, u'ä'.encode('utf-8-sig'))): |
264 |
('utf-8-sig', 2, u'\xe4'), # read as latin1! |
265 |
(None, 'ascii', (None, u'@charset "utf-8";ä'.encode('utf-8-sig'))): |
266 |
('utf-8-sig', 2, u'@charset "utf-8";\xe4'), # read as latin1! |
267 |
(None, 'ascii', (None, u'@charset "latin1";ä'.encode('utf-8-sig'))): |
268 |
('utf-8-sig', 2, u'@charset "utf-8";\xe4'), # read as latin1! |
269 |
|
270 |
|
271 |
# ===== 4. parentEncoding WINS =====
|
272 |
(None, 'latin1', (None, u''.encode())): ('latin1', 4, u''), |
273 |
(None, 'latin1', (None, u'123'.encode())): ('latin1', 4, u'123'), |
274 |
(None, 'latin1', (None, u'ä'.encode('iso-8859-1'))): |
275 |
('latin1', 4, u'ä'), |
276 |
(None, 'latin1', (None, u'a'.encode('ascii'))): |
277 |
('latin1', 4, u'a'), |
278 |
(None, 'latin1', (None, u'ä'.encode('utf-8'))): |
279 |
('latin1', 4, u'\xc3\xa4'), # read as latin1! |
280 |
|
281 |
# ===== 5. default WINS which in this case is None! =====
|
282 |
(None, None, (None, u''.encode())): ('utf-8', 5, u''), |
283 |
(None, None, (None, u'123'.encode())): ('utf-8', 5, u'123'), |
284 |
(None, None, (None, u'a'.encode('ascii'))): |
285 |
('utf-8', 5, u'a'), |
286 |
(None, None, (None, u'ä'.encode('utf-8'))): |
287 |
('utf-8', 5, u'ä'), # read as utf-8 |
288 |
(None, None, (None, u'ä'.encode('iso-8859-1'))): # trigger UnicodeDecodeError! |
289 |
('utf-8', 5, None), |
290 |
|
291 |
|
292 |
} |
293 |
for (override, parent, r), exp in tests.items(): |
294 |
self.assertEqual(_readUrl(url,
|
295 |
overrideEncoding=override, |
296 |
parentEncoding=parent, |
297 |
fetcher=make_fetcher(r)), |
298 |
exp) |
299 |
|
300 |
def test_defaultFetcher(self): |
301 |
"""util._defaultFetcher"""
|
302 |
if mock:
|
303 |
|
304 |
class Response(object): |
305 |
"""urllib2.Reponse mock"""
|
306 |
def __init__(self, url, |
307 |
contenttype, content, |
308 |
exception=None, args=None): |
309 |
self.url = url
|
310 |
|
311 |
mt, params = cgi.parse_header(contenttype) |
312 |
self.mimetype = mt
|
313 |
self.charset = params.get('charset', None) |
314 |
|
315 |
self.text = content
|
316 |
|
317 |
self.exception = exception
|
318 |
self.args = args
|
319 |
|
320 |
def geturl(self): |
321 |
return self.url |
322 |
|
323 |
def info(self): |
324 |
mimetype, charset = self.mimetype, self.charset |
325 |
class Info(object): |
326 |
|
327 |
# py2x
|
328 |
def gettype(self): |
329 |
return mimetype
|
330 |
def getparam(self, name=None): |
331 |
return charset
|
332 |
|
333 |
# py 3x
|
334 |
get_content_type = gettype |
335 |
get_content_charset = getparam # here always charset!
|
336 |
|
337 |
return Info()
|
338 |
|
339 |
def read(self): |
340 |
# returns fake text or raises fake exception
|
341 |
if not self.exception: |
342 |
return self.text |
343 |
else:
|
344 |
raise self.exception(*self.args) |
345 |
|
346 |
def urlopen(url, |
347 |
contenttype=None, content=None, |
348 |
exception=None, args=None): |
349 |
# return an mock which returns parameterized Response
|
350 |
def x(*ignored): |
351 |
if exception:
|
352 |
raise exception(*args)
|
353 |
else:
|
354 |
return Response(url,
|
355 |
contenttype, content, |
356 |
exception=exception, args=args) |
357 |
return x
|
358 |
|
359 |
urlopenpatch = 'urllib2.urlopen' if basetest.PY2x else 'urllib.request.urlopen' |
360 |
|
361 |
# positive tests
|
362 |
tests = { |
363 |
# content-type, contentstr: encoding, contentstr
|
364 |
('text/css', u'€'.encode('utf-8')): |
365 |
(None, u'€'.encode('utf-8')), |
366 |
('text/css;charset=utf-8', u'€'.encode('utf-8')): |
367 |
('utf-8', u'€'.encode('utf-8')), |
368 |
('text/css;charset=ascii', 'a'): |
369 |
('ascii', 'a') |
370 |
} |
371 |
url = 'http://example.com/test.css'
|
372 |
for (contenttype, content), exp in tests.items(): |
373 |
@mock.patch(urlopenpatch, new=urlopen(url, contenttype, content))
|
374 |
def do(url): |
375 |
return _defaultFetcher(url)
|
376 |
|
377 |
self.assertEqual(exp, do(url))
|
378 |
|
379 |
# wrong mimetype
|
380 |
@mock.patch(urlopenpatch, new=urlopen(url, 'text/html', 'a')) |
381 |
def do(url): |
382 |
return _defaultFetcher(url)
|
383 |
|
384 |
self.assertRaises(ValueError, do, url) |
385 |
|
386 |
# calling url results in fake exception
|
387 |
|
388 |
# py2 ~= py3 raises error earlier than urlopen!
|
389 |
tests = { |
390 |
'1': (ValueError, ['invalid value for url']), |
391 |
#_readUrl('mailto:a.css')
|
392 |
'mailto:e4': (urllib2.URLError, ['urlerror']), |
393 |
# cannot resolve x, IOError
|
394 |
'http://x': (urllib2.URLError, ['ioerror']), |
395 |
} |
396 |
for url, (exception, args) in tests.items(): |
397 |
@mock.patch(urlopenpatch, new=urlopen(url, exception=exception, args=args))
|
398 |
def do(url): |
399 |
return _defaultFetcher(url)
|
400 |
|
401 |
self.assertRaises(exception, do, url)
|
402 |
|
403 |
# py2 != py3 raises error earlier than urlopen!
|
404 |
urlrequestpatch = 'urllib2.urlopen' if basetest.PY2x else 'urllib.request.Request' |
405 |
tests = { |
406 |
#_readUrl('http://cthedot.de/__UNKNOWN__.css')
|
407 |
'e2': (urllib2.HTTPError, ['u', 500, 'server error', {}, None]), |
408 |
'e3': (urllib2.HTTPError, ['u', 404, 'not found', {}, None]), |
409 |
} |
410 |
for url, (exception, args) in tests.items(): |
411 |
@mock.patch(urlrequestpatch, new=urlopen(url, exception=exception, args=args))
|
412 |
def do(url): |
413 |
return _defaultFetcher(url)
|
414 |
|
415 |
self.assertRaises(exception, do, url)
|
416 |
|
417 |
else:
|
418 |
self.assertEqual(False, u'Mock needed for this test') |
419 |
|
420 |
if __name__ == '__main__': |
421 |
import unittest |
422 |
unittest.main() |