1 # xml.etree test for cElementTree
2 import io
3 import struct
4 from test import support
5 from test.support.import_helper import import_fresh_module
6 import types
7 import unittest
8
9 cET = import_fresh_module('xml.etree.ElementTree',
10 fresh=['_elementtree'])
11 cET_alias = import_fresh_module('xml.etree.cElementTree',
12 fresh=['_elementtree', 'xml.etree'],
13 deprecated=True)
14
15
16 @unittest.skipUnless(cET, 'requires _elementtree')
17 class ESC[4;38;5;81mMiscTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
18 # Issue #8651.
19 @support.bigmemtest(size=support._2G + 100, memuse=1, dry_run=False)
20 def test_length_overflow(self, size):
21 data = b'x' * size
22 parser = cET.XMLParser()
23 try:
24 self.assertRaises(OverflowError, parser.feed, data)
25 finally:
26 data = None
27
28 def test_del_attribute(self):
29 element = cET.Element('tag')
30
31 element.tag = 'TAG'
32 with self.assertRaises(AttributeError):
33 del element.tag
34 self.assertEqual(element.tag, 'TAG')
35
36 with self.assertRaises(AttributeError):
37 del element.text
38 self.assertIsNone(element.text)
39 element.text = 'TEXT'
40 with self.assertRaises(AttributeError):
41 del element.text
42 self.assertEqual(element.text, 'TEXT')
43
44 with self.assertRaises(AttributeError):
45 del element.tail
46 self.assertIsNone(element.tail)
47 element.tail = 'TAIL'
48 with self.assertRaises(AttributeError):
49 del element.tail
50 self.assertEqual(element.tail, 'TAIL')
51
52 with self.assertRaises(AttributeError):
53 del element.attrib
54 self.assertEqual(element.attrib, {})
55 element.attrib = {'A': 'B', 'C': 'D'}
56 with self.assertRaises(AttributeError):
57 del element.attrib
58 self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
59
60 def test_trashcan(self):
61 # If this test fails, it will most likely die via segfault.
62 e = root = cET.Element('root')
63 for i in range(200000):
64 e = cET.SubElement(e, 'x')
65 del e
66 del root
67 support.gc_collect()
68
69 def test_parser_ref_cycle(self):
70 # bpo-31499: xmlparser_dealloc() crashed with a segmentation fault when
71 # xmlparser_gc_clear() was called previously by the garbage collector,
72 # when the parser was part of a reference cycle.
73
74 def parser_ref_cycle():
75 parser = cET.XMLParser()
76 # Create a reference cycle using an exception to keep the frame
77 # alive, so the parser will be destroyed by the garbage collector
78 try:
79 raise ValueError
80 except ValueError as exc:
81 err = exc
82
83 # Create a parser part of reference cycle
84 parser_ref_cycle()
85 # Trigger an explicit garbage collection to break the reference cycle
86 # and so destroy the parser
87 support.gc_collect()
88
89 def test_bpo_31728(self):
90 # A crash or an assertion failure shouldn't happen, in case garbage
91 # collection triggers a call to clear() or a reading of text or tail,
92 # while a setter or clear() or __setstate__() is already running.
93 elem = cET.Element('elem')
94 class ESC[4;38;5;81mX:
95 def __del__(self):
96 elem.text
97 elem.tail
98 elem.clear()
99
100 elem.text = X()
101 elem.clear() # shouldn't crash
102
103 elem.tail = X()
104 elem.clear() # shouldn't crash
105
106 elem.text = X()
107 elem.text = X() # shouldn't crash
108 elem.clear()
109
110 elem.tail = X()
111 elem.tail = X() # shouldn't crash
112 elem.clear()
113
114 elem.text = X()
115 elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure
116 elem.clear()
117
118 elem.tail = X()
119 elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure
120
121 @support.cpython_only
122 def test_uninitialized_parser(self):
123 # The interpreter shouldn't crash in case of calling methods or
124 # accessing attributes of uninitialized XMLParser objects.
125 parser = cET.XMLParser.__new__(cET.XMLParser)
126 self.assertRaises(ValueError, parser.close)
127 self.assertRaises(ValueError, parser.feed, 'foo')
128 class ESC[4;38;5;81mMockFile:
129 def read(*args):
130 return ''
131 self.assertRaises(ValueError, parser._parse_whole, MockFile())
132 self.assertRaises(ValueError, parser._setevents, None)
133 self.assertIsNone(parser.entity)
134 self.assertIsNone(parser.target)
135
136 def test_setstate_leaks(self):
137 # Test reference leaks
138 elem = cET.Element.__new__(cET.Element)
139 for i in range(100):
140 elem.__setstate__({'tag': 'foo', 'attrib': {'bar': 42},
141 '_children': [cET.Element('child')],
142 'text': 'text goes here',
143 'tail': 'opposite of head'})
144
145 self.assertEqual(elem.tag, 'foo')
146 self.assertEqual(elem.text, 'text goes here')
147 self.assertEqual(elem.tail, 'opposite of head')
148 self.assertEqual(list(elem.attrib.items()), [('bar', 42)])
149 self.assertEqual(len(elem), 1)
150 self.assertEqual(elem[0].tag, 'child')
151
152 def test_iterparse_leaks(self):
153 # Test reference leaks in TreeBuilder (issue #35502).
154 # The test is written to be executed in the hunting reference leaks
155 # mode.
156 XML = '<a></a></b>'
157 parser = cET.iterparse(io.StringIO(XML))
158 next(parser)
159 del parser
160 support.gc_collect()
161
162 def test_xmlpullparser_leaks(self):
163 # Test reference leaks in TreeBuilder (issue #35502).
164 # The test is written to be executed in the hunting reference leaks
165 # mode.
166 XML = '<a></a></b>'
167 parser = cET.XMLPullParser()
168 parser.feed(XML)
169 del parser
170 support.gc_collect()
171
172 def test_dict_disappearing_during_get_item(self):
173 # test fix for seg fault reported in issue 27946
174 class ESC[4;38;5;81mX:
175 def __hash__(self):
176 e.attrib = {} # this frees e->extra->attrib
177 [{i: i} for i in range(1000)] # exhaust the dict keys cache
178 return 13
179
180 e = cET.Element("elem", {1: 2})
181 r = e.get(X())
182 self.assertIsNone(r)
183
184
185 @unittest.skipUnless(cET, 'requires _elementtree')
186 class ESC[4;38;5;81mTestAliasWorking(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
187 # Test that the cET alias module is alive
188 def test_alias_working(self):
189 e = cET_alias.Element('foo')
190 self.assertEqual(e.tag, 'foo')
191
192
193 @unittest.skipUnless(cET, 'requires _elementtree')
194 @support.cpython_only
195 class ESC[4;38;5;81mTestAcceleratorImported(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
196 # Test that the C accelerator was imported, as expected
197 def test_correct_import_cET(self):
198 # SubElement is a function so it retains _elementtree as its module.
199 self.assertEqual(cET.SubElement.__module__, '_elementtree')
200
201 def test_correct_import_cET_alias(self):
202 self.assertEqual(cET_alias.SubElement.__module__, '_elementtree')
203
204 def test_parser_comes_from_C(self):
205 # The type of methods defined in Python code is types.FunctionType,
206 # while the type of methods defined inside _elementtree is
207 # <class 'wrapper_descriptor'>
208 self.assertNotIsInstance(cET.Element.__init__, types.FunctionType)
209
210
211 @unittest.skipUnless(cET, 'requires _elementtree')
212 @support.cpython_only
213 class ESC[4;38;5;81mSizeofTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
214 def setUp(self):
215 self.elementsize = support.calcobjsize('5P')
216 # extra
217 self.extra = struct.calcsize('PnnP4P')
218
219 check_sizeof = support.check_sizeof
220
221 def test_element(self):
222 e = cET.Element('a')
223 self.check_sizeof(e, self.elementsize)
224
225 def test_element_with_attrib(self):
226 e = cET.Element('a', href='about:')
227 self.check_sizeof(e, self.elementsize + self.extra)
228
229 def test_element_with_children(self):
230 e = cET.Element('a')
231 for i in range(5):
232 cET.SubElement(e, 'span')
233 # should have space for 8 children now
234 self.check_sizeof(e, self.elementsize + self.extra +
235 struct.calcsize('8P'))
236
237
238 def install_tests():
239 # Test classes should have __module__ referring to this module.
240 from test import test_xml_etree
241 for name, base in vars(test_xml_etree).items():
242 if isinstance(base, type) and issubclass(base, unittest.TestCase):
243 class ESC[4;38;5;81mTemp(ESC[4;38;5;149mbase):
244 pass
245 Temp.__name__ = Temp.__qualname__ = name
246 Temp.__module__ = __name__
247 assert name not in globals()
248 globals()[name] = Temp
249
250 install_tests()
251
252 def setUpModule():
253 from test import test_xml_etree
254 test_xml_etree.setUpModule(module=cET)
255
256
257 if __name__ == '__main__':
258 unittest.main()