blob: 5f2c43244d3b7a0618e80fb03f064f54908bb87c [file] [log] [blame]
Lars Gustäbel96753b32000-09-24 12:24:24 +00001
2# regression test for SAX 2.0
3# $Id$
4
5from xml.sax.saxutils import XMLGenerator, escape, XMLFilterBase
6from xml.sax.expatreader import create_parser
Lars Gustäbelb7536d52000-09-24 18:53:56 +00007from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
Lars Gustäbelab647872000-09-24 18:40:52 +00008from xml.sax.handler import ContentHandler
Lars Gustäbel96753b32000-09-24 12:24:24 +00009from cStringIO import StringIO
Martin v. Löwis33315b12000-09-24 20:30:24 +000010from test_support import verbose, TestFailed, findfile
Lars Gustäbel96753b32000-09-24 12:24:24 +000011
12# ===== Utilities
13
14tests = 0
15fails = 0
16
17def confirm(outcome, name):
18 global tests, fails
19
20 tests = tests + 1
21 if outcome:
22 print "Passed", name
23 else:
24 print "Failed", name
25 fails = fails + 1
26
27# ===========================================================================
28#
29# saxutils tests
30#
31# ===========================================================================
32
33# ===== escape
34
35def test_escape_basic():
36 return escape("Donald Duck & Co") == "Donald Duck & Co"
37
38def test_escape_all():
39 return escape("<Donald Duck & Co>") == "&lt;Donald Duck &amp; Co&gt;"
40
41def test_escape_extra():
42 return escape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
43
44# ===== XMLGenerator
45
46start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
47
48def test_xmlgen_basic():
49 result = StringIO()
50 gen = XMLGenerator(result)
51 gen.startDocument()
52 gen.startElement("doc", {})
53 gen.endElement("doc")
54 gen.endDocument()
55
56 return result.getvalue() == start + "<doc></doc>"
57
58def test_xmlgen_content():
59 result = StringIO()
60 gen = XMLGenerator(result)
61
62 gen.startDocument()
63 gen.startElement("doc", {})
64 gen.characters("huhei")
65 gen.endElement("doc")
66 gen.endDocument()
67
68 return result.getvalue() == start + "<doc>huhei</doc>"
69
70def test_xmlgen_pi():
71 result = StringIO()
72 gen = XMLGenerator(result)
73
74 gen.startDocument()
75 gen.processingInstruction("test", "data")
76 gen.startElement("doc", {})
77 gen.endElement("doc")
78 gen.endDocument()
79
80 return result.getvalue() == start + "<?test data?><doc></doc>"
81
82def test_xmlgen_content_escape():
83 result = StringIO()
84 gen = XMLGenerator(result)
85
86 gen.startDocument()
87 gen.startElement("doc", {})
88 gen.characters("<huhei&")
89 gen.endElement("doc")
90 gen.endDocument()
91
92 return result.getvalue() == start + "<doc>&lt;huhei&amp;</doc>"
93
94def test_xmlgen_ignorable():
95 result = StringIO()
96 gen = XMLGenerator(result)
97
98 gen.startDocument()
99 gen.startElement("doc", {})
100 gen.ignorableWhitespace(" ")
101 gen.endElement("doc")
102 gen.endDocument()
103
104 return result.getvalue() == start + "<doc> </doc>"
105
106ns_uri = "http://www.python.org/xml-ns/saxtest/"
107
108def test_xmlgen_ns():
109 result = StringIO()
110 gen = XMLGenerator(result)
111
112 gen.startDocument()
113 gen.startPrefixMapping("ns1", ns_uri)
114 gen.startElementNS((ns_uri, "doc"), "ns:doc", {})
115 gen.endElementNS((ns_uri, "doc"), "ns:doc")
116 gen.endPrefixMapping("ns1")
117 gen.endDocument()
118
119 return result.getvalue() == start + ('<ns1:doc xmlns:ns1="%s"></ns1:doc>' %
120 ns_uri)
121
122# ===== XMLFilterBase
123
124def test_filter_basic():
125 result = StringIO()
126 gen = XMLGenerator(result)
127 filter = XMLFilterBase()
128 filter.setContentHandler(gen)
129
130 filter.startDocument()
131 filter.startElement("doc", {})
132 filter.characters("content")
133 filter.ignorableWhitespace(" ")
134 filter.endElement("doc")
135 filter.endDocument()
136
137 return result.getvalue() == start + "<doc>content </doc>"
138
139# ===========================================================================
140#
141# expatreader tests
142#
143# ===========================================================================
144
145# ===== DTDHandler support
146
147class TestDTDHandler:
148
149 def __init__(self):
150 self._notations = []
151 self._entities = []
152
153 def notationDecl(self, name, publicId, systemId):
154 self._notations.append((name, publicId, systemId))
155
156 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
157 self._entities.append((name, publicId, systemId, ndata))
158
Lars Gustäbele292a242000-09-24 20:19:45 +0000159def test_expat_dtdhandler():
160 parser = create_parser()
161 handler = TestDTDHandler()
162 parser.setDTDHandler(handler)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000163
Lars Gustäbele292a242000-09-24 20:19:45 +0000164 parser.feed('<!DOCTYPE doc [\n')
165 parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
166 parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
167 parser.feed(']>\n')
168 parser.feed('<doc></doc>')
169 parser.close()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000170
Lars Gustäbele292a242000-09-24 20:19:45 +0000171 return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
172 handler._entities == [("img", None, "expat.gif", "GIF")]
Lars Gustäbel96753b32000-09-24 12:24:24 +0000173
174# ===== EntityResolver support
175
Lars Gustäbele292a242000-09-24 20:19:45 +0000176class TestEntityResolver:
Lars Gustäbel96753b32000-09-24 12:24:24 +0000177
Lars Gustäbele292a242000-09-24 20:19:45 +0000178 def resolveEntity(self, publicId, systemId):
179 inpsrc = InputSource()
180 inpsrc.setByteStream(StringIO("<entity/>"))
181 return inpsrc
182
183def test_expat_entityresolver():
184 return 1 # disabling this until pyexpat.c has been fixed
185 parser = create_parser()
186 parser.setEntityResolver(TestEntityResolver())
187 result = StringIO()
188 parser.setContentHandler(XMLGenerator(result))
189
190 parser.feed('<!DOCTYPE doc [\n')
191 parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
192 parser.feed(']>\n')
193 parser.feed('<doc>&test;</doc>')
194 parser.close()
195
196 return result.getvalue() == start + "<doc><entity></entity></doc>"
197
Lars Gustäbelab647872000-09-24 18:40:52 +0000198# ===== Attributes support
199
200class AttrGatherer(ContentHandler):
201
202 def startElement(self, name, attrs):
203 self._attrs = attrs
204
205 def startElementNS(self, name, qname, attrs):
206 self._attrs = attrs
207
208def test_expat_attrs_empty():
209 parser = create_parser()
210 gather = AttrGatherer()
211 parser.setContentHandler(gather)
212
213 parser.feed("<doc/>")
214 parser.close()
215
216 return verify_empty_attrs(gather._attrs)
217
218def test_expat_attrs_wattr():
219 parser = create_parser()
220 gather = AttrGatherer()
221 parser.setContentHandler(gather)
222
223 parser.feed("<doc attr='val'/>")
224 parser.close()
225
226 return verify_attrs_wattr(gather._attrs)
227
228def test_expat_nsattrs_empty():
229 parser = create_parser(1)
230 gather = AttrGatherer()
231 parser.setContentHandler(gather)
232
233 parser.feed("<doc/>")
234 parser.close()
235
236 return verify_empty_nsattrs(gather._attrs)
237
238def test_expat_nsattrs_wattr():
239 parser = create_parser(1)
240 gather = AttrGatherer()
241 parser.setContentHandler(gather)
242
243 parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
244 parser.close()
245
246 attrs = gather._attrs
247
248 return attrs.getLength() == 1 and \
249 attrs.getNames() == [(ns_uri, "attr")] and \
250 attrs.getQNames() == [] and \
251 len(attrs) == 1 and \
252 attrs.has_key((ns_uri, "attr")) and \
253 attrs.keys() == [(ns_uri, "attr")] and \
254 attrs.get((ns_uri, "attr")) == "val" and \
255 attrs.get((ns_uri, "attr"), 25) == "val" and \
256 attrs.items() == [((ns_uri, "attr"), "val")] and \
257 attrs.values() == ["val"] and \
258 attrs.getValue((ns_uri, "attr")) == "val" and \
259 attrs[(ns_uri, "attr")] == "val"
260
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000261# ===== InputSource support
262
Martin v. Löwis33315b12000-09-24 20:30:24 +0000263xml_test_out = open(findfile("test.xml.out")).read()
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000264
265def test_expat_inpsource_filename():
266 parser = create_parser()
267 result = StringIO()
268 xmlgen = XMLGenerator(result)
269
270 parser.setContentHandler(xmlgen)
Martin v. Löwis33315b12000-09-24 20:30:24 +0000271 parser.parse(findfile("test.xml"))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000272
273 return result.getvalue() == xml_test_out
274
275def test_expat_inpsource_sysid():
276 parser = create_parser()
277 result = StringIO()
278 xmlgen = XMLGenerator(result)
279
280 parser.setContentHandler(xmlgen)
Martin v. Löwis33315b12000-09-24 20:30:24 +0000281 parser.parse(InputSource(findfile("test.xml")))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000282
283 return result.getvalue() == xml_test_out
284
285def test_expat_inpsource_stream():
286 parser = create_parser()
287 result = StringIO()
288 xmlgen = XMLGenerator(result)
289
290 parser.setContentHandler(xmlgen)
291 inpsrc = InputSource()
Martin v. Löwis33315b12000-09-24 20:30:24 +0000292 inpsrc.setByteStream(open(findfile("test.xml")))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000293 parser.parse(inpsrc)
294
295 return result.getvalue() == xml_test_out
296
Lars Gustäbelab647872000-09-24 18:40:52 +0000297# ===========================================================================
298#
299# xmlreader tests
300#
301# ===========================================================================
302
303# ===== AttributesImpl
304
305def verify_empty_attrs(attrs):
306 try:
307 attrs.getValue("attr")
308 gvk = 0
309 except KeyError:
310 gvk = 1
311
312 try:
313 attrs.getValueByQName("attr")
314 gvqk = 0
315 except KeyError:
316 gvqk = 1
317
318 try:
319 attrs.getNameByQName("attr")
320 gnqk = 0
321 except KeyError:
322 gnqk = 1
323
324 try:
325 attrs.getQNameByName("attr")
326 gqnk = 0
327 except KeyError:
328 gqnk = 1
329
330 try:
331 attrs["attr"]
332 gik = 0
333 except KeyError:
334 gik = 1
335
336 return attrs.getLength() == 0 and \
337 attrs.getNames() == [] and \
338 attrs.getQNames() == [] and \
339 len(attrs) == 0 and \
340 not attrs.has_key("attr") and \
341 attrs.keys() == [] and \
342 attrs.get("attrs") == None and \
343 attrs.get("attrs", 25) == 25 and \
344 attrs.items() == [] and \
345 attrs.values() == [] and \
346 gvk and gvqk and gnqk and gik and gqnk
347
348def verify_attrs_wattr(attrs):
349 return attrs.getLength() == 1 and \
350 attrs.getNames() == ["attr"] and \
351 attrs.getQNames() == ["attr"] and \
352 len(attrs) == 1 and \
353 attrs.has_key("attr") and \
354 attrs.keys() == ["attr"] and \
355 attrs.get("attr") == "val" and \
356 attrs.get("attr", 25) == "val" and \
357 attrs.items() == [("attr", "val")] and \
358 attrs.values() == ["val"] and \
359 attrs.getValue("attr") == "val" and \
360 attrs.getValueByQName("attr") == "val" and \
361 attrs.getNameByQName("attr") == "attr" and \
362 attrs["attr"] == "val" and \
363 attrs.getQNameByName("attr") == "attr"
364
365def test_attrs_empty():
366 return verify_empty_attrs(AttributesImpl({}))
367
368def test_attrs_wattr():
369 return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
370
371# ===== AttributesImpl
372
373def verify_empty_nsattrs(attrs):
374 try:
375 attrs.getValue((ns_uri, "attr"))
376 gvk = 0
377 except KeyError:
378 gvk = 1
379
380 try:
381 attrs.getValueByQName("ns:attr")
382 gvqk = 0
383 except KeyError:
384 gvqk = 1
385
386 try:
387 attrs.getNameByQName("ns:attr")
388 gnqk = 0
389 except KeyError:
390 gnqk = 1
391
392 try:
393 attrs.getQNameByName((ns_uri, "attr"))
394 gqnk = 0
395 except KeyError:
396 gqnk = 1
397
398 try:
399 attrs[(ns_uri, "attr")]
400 gik = 0
401 except KeyError:
402 gik = 1
403
404 return attrs.getLength() == 0 and \
405 attrs.getNames() == [] and \
406 attrs.getQNames() == [] and \
407 len(attrs) == 0 and \
408 not attrs.has_key((ns_uri, "attr")) and \
409 attrs.keys() == [] and \
410 attrs.get((ns_uri, "attr")) == None and \
411 attrs.get((ns_uri, "attr"), 25) == 25 and \
412 attrs.items() == [] and \
413 attrs.values() == [] and \
414 gvk and gvqk and gnqk and gik and gqnk
415
416def test_nsattrs_empty():
417 return verify_empty_nsattrs(AttributesNSImpl({}, {}))
418
419def test_nsattrs_wattr():
420 attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
421 {(ns_uri, "attr") : "ns:attr"})
422
423 return attrs.getLength() == 1 and \
424 attrs.getNames() == [(ns_uri, "attr")] and \
425 attrs.getQNames() == ["ns:attr"] and \
426 len(attrs) == 1 and \
427 attrs.has_key((ns_uri, "attr")) and \
428 attrs.keys() == [(ns_uri, "attr")] and \
429 attrs.get((ns_uri, "attr")) == "val" and \
430 attrs.get((ns_uri, "attr"), 25) == "val" and \
431 attrs.items() == [((ns_uri, "attr"), "val")] and \
432 attrs.values() == ["val"] and \
433 attrs.getValue((ns_uri, "attr")) == "val" and \
434 attrs.getValueByQName("ns:attr") == "val" and \
435 attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
436 attrs[(ns_uri, "attr")] == "val" and \
437 attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
438
439
Lars Gustäbel96753b32000-09-24 12:24:24 +0000440# ===== Main program
441
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000442def make_test_output():
443 parser = create_parser()
444 result = StringIO()
445 xmlgen = XMLGenerator(result)
446
447 parser.setContentHandler(xmlgen)
Martin v. Löwis33315b12000-09-24 20:30:24 +0000448 parser.parse(findfile("test.xml"))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000449
Martin v. Löwis33315b12000-09-24 20:30:24 +0000450 outf = open(findfile("test.xml.out"), "w")
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000451 outf.write(result.getvalue())
452 outf.close()
453
Lars Gustäbel96753b32000-09-24 12:24:24 +0000454items = locals().items()
455items.sort()
456for (name, value) in items:
457 if name[ : 5] == "test_":
458 confirm(value(), name)
459
460print "%d tests, %d failures" % (tests, fails)
461if fails != 0:
462 raise TestFailed, "%d of %d tests failed" % (fails, tests)