17db96d56Sopenharmony_ci# xml.etree test for cElementTree 27db96d56Sopenharmony_ciimport io 37db96d56Sopenharmony_ciimport struct 47db96d56Sopenharmony_cifrom test import support 57db96d56Sopenharmony_cifrom test.support.import_helper import import_fresh_module 67db96d56Sopenharmony_ciimport types 77db96d56Sopenharmony_ciimport unittest 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_cicET = import_fresh_module('xml.etree.ElementTree', 107db96d56Sopenharmony_ci fresh=['_elementtree']) 117db96d56Sopenharmony_cicET_alias = import_fresh_module('xml.etree.cElementTree', 127db96d56Sopenharmony_ci fresh=['_elementtree', 'xml.etree'], 137db96d56Sopenharmony_ci deprecated=True) 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci@unittest.skipUnless(cET, 'requires _elementtree') 177db96d56Sopenharmony_ciclass MiscTests(unittest.TestCase): 187db96d56Sopenharmony_ci # Issue #8651. 197db96d56Sopenharmony_ci @support.bigmemtest(size=support._2G + 100, memuse=1, dry_run=False) 207db96d56Sopenharmony_ci def test_length_overflow(self, size): 217db96d56Sopenharmony_ci data = b'x' * size 227db96d56Sopenharmony_ci parser = cET.XMLParser() 237db96d56Sopenharmony_ci try: 247db96d56Sopenharmony_ci self.assertRaises(OverflowError, parser.feed, data) 257db96d56Sopenharmony_ci finally: 267db96d56Sopenharmony_ci data = None 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci def test_del_attribute(self): 297db96d56Sopenharmony_ci element = cET.Element('tag') 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci element.tag = 'TAG' 327db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 337db96d56Sopenharmony_ci del element.tag 347db96d56Sopenharmony_ci self.assertEqual(element.tag, 'TAG') 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 377db96d56Sopenharmony_ci del element.text 387db96d56Sopenharmony_ci self.assertIsNone(element.text) 397db96d56Sopenharmony_ci element.text = 'TEXT' 407db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 417db96d56Sopenharmony_ci del element.text 427db96d56Sopenharmony_ci self.assertEqual(element.text, 'TEXT') 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 457db96d56Sopenharmony_ci del element.tail 467db96d56Sopenharmony_ci self.assertIsNone(element.tail) 477db96d56Sopenharmony_ci element.tail = 'TAIL' 487db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 497db96d56Sopenharmony_ci del element.tail 507db96d56Sopenharmony_ci self.assertEqual(element.tail, 'TAIL') 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 537db96d56Sopenharmony_ci del element.attrib 547db96d56Sopenharmony_ci self.assertEqual(element.attrib, {}) 557db96d56Sopenharmony_ci element.attrib = {'A': 'B', 'C': 'D'} 567db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 577db96d56Sopenharmony_ci del element.attrib 587db96d56Sopenharmony_ci self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'}) 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci def test_trashcan(self): 617db96d56Sopenharmony_ci # If this test fails, it will most likely die via segfault. 627db96d56Sopenharmony_ci e = root = cET.Element('root') 637db96d56Sopenharmony_ci for i in range(200000): 647db96d56Sopenharmony_ci e = cET.SubElement(e, 'x') 657db96d56Sopenharmony_ci del e 667db96d56Sopenharmony_ci del root 677db96d56Sopenharmony_ci support.gc_collect() 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci def test_parser_ref_cycle(self): 707db96d56Sopenharmony_ci # bpo-31499: xmlparser_dealloc() crashed with a segmentation fault when 717db96d56Sopenharmony_ci # xmlparser_gc_clear() was called previously by the garbage collector, 727db96d56Sopenharmony_ci # when the parser was part of a reference cycle. 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci def parser_ref_cycle(): 757db96d56Sopenharmony_ci parser = cET.XMLParser() 767db96d56Sopenharmony_ci # Create a reference cycle using an exception to keep the frame 777db96d56Sopenharmony_ci # alive, so the parser will be destroyed by the garbage collector 787db96d56Sopenharmony_ci try: 797db96d56Sopenharmony_ci raise ValueError 807db96d56Sopenharmony_ci except ValueError as exc: 817db96d56Sopenharmony_ci err = exc 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci # Create a parser part of reference cycle 847db96d56Sopenharmony_ci parser_ref_cycle() 857db96d56Sopenharmony_ci # Trigger an explicit garbage collection to break the reference cycle 867db96d56Sopenharmony_ci # and so destroy the parser 877db96d56Sopenharmony_ci support.gc_collect() 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci def test_bpo_31728(self): 907db96d56Sopenharmony_ci # A crash or an assertion failure shouldn't happen, in case garbage 917db96d56Sopenharmony_ci # collection triggers a call to clear() or a reading of text or tail, 927db96d56Sopenharmony_ci # while a setter or clear() or __setstate__() is already running. 937db96d56Sopenharmony_ci elem = cET.Element('elem') 947db96d56Sopenharmony_ci class X: 957db96d56Sopenharmony_ci def __del__(self): 967db96d56Sopenharmony_ci elem.text 977db96d56Sopenharmony_ci elem.tail 987db96d56Sopenharmony_ci elem.clear() 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci elem.text = X() 1017db96d56Sopenharmony_ci elem.clear() # shouldn't crash 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci elem.tail = X() 1047db96d56Sopenharmony_ci elem.clear() # shouldn't crash 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci elem.text = X() 1077db96d56Sopenharmony_ci elem.text = X() # shouldn't crash 1087db96d56Sopenharmony_ci elem.clear() 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci elem.tail = X() 1117db96d56Sopenharmony_ci elem.tail = X() # shouldn't crash 1127db96d56Sopenharmony_ci elem.clear() 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci elem.text = X() 1157db96d56Sopenharmony_ci elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure 1167db96d56Sopenharmony_ci elem.clear() 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci elem.tail = X() 1197db96d56Sopenharmony_ci elem.__setstate__({'tag': 42}) # shouldn't cause an assertion failure 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci @support.cpython_only 1227db96d56Sopenharmony_ci def test_uninitialized_parser(self): 1237db96d56Sopenharmony_ci # The interpreter shouldn't crash in case of calling methods or 1247db96d56Sopenharmony_ci # accessing attributes of uninitialized XMLParser objects. 1257db96d56Sopenharmony_ci parser = cET.XMLParser.__new__(cET.XMLParser) 1267db96d56Sopenharmony_ci self.assertRaises(ValueError, parser.close) 1277db96d56Sopenharmony_ci self.assertRaises(ValueError, parser.feed, 'foo') 1287db96d56Sopenharmony_ci class MockFile: 1297db96d56Sopenharmony_ci def read(*args): 1307db96d56Sopenharmony_ci return '' 1317db96d56Sopenharmony_ci self.assertRaises(ValueError, parser._parse_whole, MockFile()) 1327db96d56Sopenharmony_ci self.assertRaises(ValueError, parser._setevents, None) 1337db96d56Sopenharmony_ci self.assertIsNone(parser.entity) 1347db96d56Sopenharmony_ci self.assertIsNone(parser.target) 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci def test_setstate_leaks(self): 1377db96d56Sopenharmony_ci # Test reference leaks 1387db96d56Sopenharmony_ci elem = cET.Element.__new__(cET.Element) 1397db96d56Sopenharmony_ci for i in range(100): 1407db96d56Sopenharmony_ci elem.__setstate__({'tag': 'foo', 'attrib': {'bar': 42}, 1417db96d56Sopenharmony_ci '_children': [cET.Element('child')], 1427db96d56Sopenharmony_ci 'text': 'text goes here', 1437db96d56Sopenharmony_ci 'tail': 'opposite of head'}) 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci self.assertEqual(elem.tag, 'foo') 1467db96d56Sopenharmony_ci self.assertEqual(elem.text, 'text goes here') 1477db96d56Sopenharmony_ci self.assertEqual(elem.tail, 'opposite of head') 1487db96d56Sopenharmony_ci self.assertEqual(list(elem.attrib.items()), [('bar', 42)]) 1497db96d56Sopenharmony_ci self.assertEqual(len(elem), 1) 1507db96d56Sopenharmony_ci self.assertEqual(elem[0].tag, 'child') 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci def test_iterparse_leaks(self): 1537db96d56Sopenharmony_ci # Test reference leaks in TreeBuilder (issue #35502). 1547db96d56Sopenharmony_ci # The test is written to be executed in the hunting reference leaks 1557db96d56Sopenharmony_ci # mode. 1567db96d56Sopenharmony_ci XML = '<a></a></b>' 1577db96d56Sopenharmony_ci parser = cET.iterparse(io.StringIO(XML)) 1587db96d56Sopenharmony_ci next(parser) 1597db96d56Sopenharmony_ci del parser 1607db96d56Sopenharmony_ci support.gc_collect() 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci def test_xmlpullparser_leaks(self): 1637db96d56Sopenharmony_ci # Test reference leaks in TreeBuilder (issue #35502). 1647db96d56Sopenharmony_ci # The test is written to be executed in the hunting reference leaks 1657db96d56Sopenharmony_ci # mode. 1667db96d56Sopenharmony_ci XML = '<a></a></b>' 1677db96d56Sopenharmony_ci parser = cET.XMLPullParser() 1687db96d56Sopenharmony_ci parser.feed(XML) 1697db96d56Sopenharmony_ci del parser 1707db96d56Sopenharmony_ci support.gc_collect() 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci def test_dict_disappearing_during_get_item(self): 1737db96d56Sopenharmony_ci # test fix for seg fault reported in issue 27946 1747db96d56Sopenharmony_ci class X: 1757db96d56Sopenharmony_ci def __hash__(self): 1767db96d56Sopenharmony_ci e.attrib = {} # this frees e->extra->attrib 1777db96d56Sopenharmony_ci [{i: i} for i in range(1000)] # exhaust the dict keys cache 1787db96d56Sopenharmony_ci return 13 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci e = cET.Element("elem", {1: 2}) 1817db96d56Sopenharmony_ci r = e.get(X()) 1827db96d56Sopenharmony_ci self.assertIsNone(r) 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci@unittest.skipUnless(cET, 'requires _elementtree') 1867db96d56Sopenharmony_ciclass TestAliasWorking(unittest.TestCase): 1877db96d56Sopenharmony_ci # Test that the cET alias module is alive 1887db96d56Sopenharmony_ci def test_alias_working(self): 1897db96d56Sopenharmony_ci e = cET_alias.Element('foo') 1907db96d56Sopenharmony_ci self.assertEqual(e.tag, 'foo') 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci@unittest.skipUnless(cET, 'requires _elementtree') 1947db96d56Sopenharmony_ci@support.cpython_only 1957db96d56Sopenharmony_ciclass TestAcceleratorImported(unittest.TestCase): 1967db96d56Sopenharmony_ci # Test that the C accelerator was imported, as expected 1977db96d56Sopenharmony_ci def test_correct_import_cET(self): 1987db96d56Sopenharmony_ci # SubElement is a function so it retains _elementtree as its module. 1997db96d56Sopenharmony_ci self.assertEqual(cET.SubElement.__module__, '_elementtree') 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci def test_correct_import_cET_alias(self): 2027db96d56Sopenharmony_ci self.assertEqual(cET_alias.SubElement.__module__, '_elementtree') 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci def test_parser_comes_from_C(self): 2057db96d56Sopenharmony_ci # The type of methods defined in Python code is types.FunctionType, 2067db96d56Sopenharmony_ci # while the type of methods defined inside _elementtree is 2077db96d56Sopenharmony_ci # <class 'wrapper_descriptor'> 2087db96d56Sopenharmony_ci self.assertNotIsInstance(cET.Element.__init__, types.FunctionType) 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci@unittest.skipUnless(cET, 'requires _elementtree') 2127db96d56Sopenharmony_ci@support.cpython_only 2137db96d56Sopenharmony_ciclass SizeofTest(unittest.TestCase): 2147db96d56Sopenharmony_ci def setUp(self): 2157db96d56Sopenharmony_ci self.elementsize = support.calcobjsize('5P') 2167db96d56Sopenharmony_ci # extra 2177db96d56Sopenharmony_ci self.extra = struct.calcsize('PnnP4P') 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ci check_sizeof = support.check_sizeof 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci def test_element(self): 2227db96d56Sopenharmony_ci e = cET.Element('a') 2237db96d56Sopenharmony_ci self.check_sizeof(e, self.elementsize) 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci def test_element_with_attrib(self): 2267db96d56Sopenharmony_ci e = cET.Element('a', href='about:') 2277db96d56Sopenharmony_ci self.check_sizeof(e, self.elementsize + self.extra) 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci def test_element_with_children(self): 2307db96d56Sopenharmony_ci e = cET.Element('a') 2317db96d56Sopenharmony_ci for i in range(5): 2327db96d56Sopenharmony_ci cET.SubElement(e, 'span') 2337db96d56Sopenharmony_ci # should have space for 8 children now 2347db96d56Sopenharmony_ci self.check_sizeof(e, self.elementsize + self.extra + 2357db96d56Sopenharmony_ci struct.calcsize('8P')) 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_cidef test_main(): 2387db96d56Sopenharmony_ci from test import test_xml_etree 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci # Run the tests specific to the C implementation 2417db96d56Sopenharmony_ci support.run_unittest( 2427db96d56Sopenharmony_ci MiscTests, 2437db96d56Sopenharmony_ci TestAliasWorking, 2447db96d56Sopenharmony_ci TestAcceleratorImported, 2457db96d56Sopenharmony_ci SizeofTest, 2467db96d56Sopenharmony_ci ) 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci # Run the same test suite as the Python module 2497db96d56Sopenharmony_ci test_xml_etree.test_main(module=cET) 2507db96d56Sopenharmony_ci 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ciif __name__ == '__main__': 2537db96d56Sopenharmony_ci test_main() 254