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 @support.cpython_only
185 def test_immutable_types(self):
186 root = cET.fromstring('<a></a>')
187 dataset = (
188 cET.Element,
189 cET.TreeBuilder,
190 cET.XMLParser,
191 type(root.iter()),
192 )
193 for tp in dataset:
194 with self.subTest(tp=tp):
195 with self.assertRaisesRegex(TypeError, "immutable"):
196 tp.foo = 1
197
198 @support.cpython_only
199 def test_disallow_instantiation(self):
200 root = cET.fromstring('<a></a>')
201 iter_type = type(root.iter())
202 support.check_disallow_instantiation(self, iter_type)
203
204
205 @unittest.skipUnless(cET, 'requires _elementtree')
206 class ESC[4;38;5;81mTestAliasWorking(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
207 # Test that the cET alias module is alive
208 def test_alias_working(self):
209 e = cET_alias.Element('foo')
210 self.assertEqual(e.tag, 'foo')
211
212
213 @unittest.skipUnless(cET, 'requires _elementtree')
214 @support.cpython_only
215 class ESC[4;38;5;81mTestAcceleratorImported(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
216 # Test that the C accelerator was imported, as expected
217 def test_correct_import_cET(self):
218 # SubElement is a function so it retains _elementtree as its module.
219 self.assertEqual(cET.SubElement.__module__, '_elementtree')
220
221 def test_correct_import_cET_alias(self):
222 self.assertEqual(cET_alias.SubElement.__module__, '_elementtree')
223
224 def test_parser_comes_from_C(self):
225 # The type of methods defined in Python code is types.FunctionType,
226 # while the type of methods defined inside _elementtree is
227 # <class 'wrapper_descriptor'>
228 self.assertNotIsInstance(cET.Element.__init__, types.FunctionType)
229
230
231 @unittest.skipUnless(cET, 'requires _elementtree')
232 @support.cpython_only
233 class ESC[4;38;5;81mSizeofTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
234 def setUp(self):
235 self.elementsize = support.calcobjsize('5P')
236 # extra
237 self.extra = struct.calcsize('PnnP4P')
238
239 check_sizeof = support.check_sizeof
240
241 def test_element(self):
242 e = cET.Element('a')
243 self.check_sizeof(e, self.elementsize)
244
245 def test_element_with_attrib(self):
246 e = cET.Element('a', href='about:')
247 self.check_sizeof(e, self.elementsize + self.extra)
248
249 def test_element_with_children(self):
250 e = cET.Element('a')
251 for i in range(5):
252 cET.SubElement(e, 'span')
253 # should have space for 8 children now
254 self.check_sizeof(e, self.elementsize + self.extra +
255 struct.calcsize('8P'))
256
257
258 def install_tests():
259 # Test classes should have __module__ referring to this module.
260 from test import test_xml_etree
261 for name, base in vars(test_xml_etree).items():
262 if isinstance(base, type) and issubclass(base, unittest.TestCase):
263 class ESC[4;38;5;81mTemp(ESC[4;38;5;149mbase):
264 pass
265 Temp.__name__ = Temp.__qualname__ = name
266 Temp.__module__ = __name__
267 assert name not in globals()
268 globals()[name] = Temp
269
270 install_tests()
271
272 def setUpModule():
273 from test import test_xml_etree
274 test_xml_etree.setUpModule(module=cET)
275
276
277 if __name__ == '__main__':
278 unittest.main()