1# xml.etree test for cElementTree 2import io 3import struct 4from test import support 5from test.support import import_fresh_module 6import types 7import unittest 8 9cET = import_fresh_module('xml.etree.ElementTree', 10 fresh=['_elementtree']) 11cET_alias = import_fresh_module('xml.etree.cElementTree', 12 fresh=['_elementtree', 'xml.etree'], 13 deprecated=True) 14 15 16@unittest.skipUnless(cET, 'requires _elementtree') 17class MiscTests(unittest.TestCase): 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 X: 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 def test_setstate_leaks(self): 122 # Test reference leaks 123 elem = cET.Element.__new__(cET.Element) 124 for i in range(100): 125 elem.__setstate__({'tag': 'foo', 'attrib': {'bar': 42}, 126 '_children': [cET.Element('child')], 127 'text': 'text goes here', 128 'tail': 'opposite of head'}) 129 130 self.assertEqual(elem.tag, 'foo') 131 self.assertEqual(elem.text, 'text goes here') 132 self.assertEqual(elem.tail, 'opposite of head') 133 self.assertEqual(list(elem.attrib.items()), [('bar', 42)]) 134 self.assertEqual(len(elem), 1) 135 self.assertEqual(elem[0].tag, 'child') 136 137 def test_iterparse_leaks(self): 138 # Test reference leaks in TreeBuilder (issue #35502). 139 # The test is written to be executed in the hunting reference leaks 140 # mode. 141 XML = '<a></a></b>' 142 parser = cET.iterparse(io.StringIO(XML)) 143 next(parser) 144 del parser 145 support.gc_collect() 146 147 def test_xmlpullparser_leaks(self): 148 # Test reference leaks in TreeBuilder (issue #35502). 149 # The test is written to be executed in the hunting reference leaks 150 # mode. 151 XML = '<a></a></b>' 152 parser = cET.XMLPullParser() 153 parser.feed(XML) 154 del parser 155 support.gc_collect() 156 157 158@unittest.skipUnless(cET, 'requires _elementtree') 159class TestAliasWorking(unittest.TestCase): 160 # Test that the cET alias module is alive 161 def test_alias_working(self): 162 e = cET_alias.Element('foo') 163 self.assertEqual(e.tag, 'foo') 164 165 166@unittest.skipUnless(cET, 'requires _elementtree') 167@support.cpython_only 168class TestAcceleratorImported(unittest.TestCase): 169 # Test that the C accelerator was imported, as expected 170 def test_correct_import_cET(self): 171 # SubElement is a function so it retains _elementtree as its module. 172 self.assertEqual(cET.SubElement.__module__, '_elementtree') 173 174 def test_correct_import_cET_alias(self): 175 self.assertEqual(cET_alias.SubElement.__module__, '_elementtree') 176 177 def test_parser_comes_from_C(self): 178 # The type of methods defined in Python code is types.FunctionType, 179 # while the type of methods defined inside _elementtree is 180 # <class 'wrapper_descriptor'> 181 self.assertNotIsInstance(cET.Element.__init__, types.FunctionType) 182 183 184@unittest.skipUnless(cET, 'requires _elementtree') 185@support.cpython_only 186class SizeofTest(unittest.TestCase): 187 def setUp(self): 188 self.elementsize = support.calcobjsize('5P') 189 # extra 190 self.extra = struct.calcsize('PnnP4P') 191 192 check_sizeof = support.check_sizeof 193 194 def test_element(self): 195 e = cET.Element('a') 196 self.check_sizeof(e, self.elementsize) 197 198 def test_element_with_attrib(self): 199 e = cET.Element('a', href='about:') 200 self.check_sizeof(e, self.elementsize + self.extra) 201 202 def test_element_with_children(self): 203 e = cET.Element('a') 204 for i in range(5): 205 cET.SubElement(e, 'span') 206 # should have space for 8 children now 207 self.check_sizeof(e, self.elementsize + self.extra + 208 struct.calcsize('8P')) 209 210def test_main(): 211 from test import test_xml_etree 212 213 # Run the tests specific to the C implementation 214 support.run_unittest( 215 MiscTests, 216 TestAliasWorking, 217 TestAcceleratorImported, 218 SizeofTest, 219 ) 220 221 # Run the same test suite as the Python module 222 test_xml_etree.test_main(module=cET) 223 224 225if __name__ == '__main__': 226 test_main() 227