(root)/
Python-3.12.0/
Lib/
test/
test_xml_etree_c.py
       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()