blob: 2144d203e1e95ce1cc8716154c1ca76830546580 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001# xml.etree test for cElementTree
Serhiy Storchakad2a75c62018-12-18 22:29:14 +02002import io
Berker Peksag1e8ee9b2016-04-24 07:31:42 +03003import struct
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Florent Xicluna6c3da6e2012-02-13 12:14:52 +01005from test.support import import_fresh_module
Eli Benderskye26fa1b2013-05-19 17:49:54 -07006import types
Victor Stinnerb3c9e072011-01-04 02:07:34 +00007import unittest
Fredrik Lundh9235ea42005-12-15 18:41:22 +00008
Eli Bendersky23687042013-02-26 05:53:23 -08009cET = import_fresh_module('xml.etree.ElementTree',
10 fresh=['_elementtree'])
11cET_alias = import_fresh_module('xml.etree.cElementTree',
Serhiy Storchaka762ec972017-03-30 18:12:06 +030012 fresh=['_elementtree', 'xml.etree'],
13 deprecated=True)
Fredrik Lundh8911ca3d2005-12-16 22:07:17 +000014
Fredrik Lundh9235ea42005-12-15 18:41:22 +000015
Serhiy Storchaka18f018c2016-12-21 12:32:56 +020016@unittest.skipUnless(cET, 'requires _elementtree')
Victor Stinnerb3c9e072011-01-04 02:07:34 +000017class MiscTests(unittest.TestCase):
18 # Issue #8651.
Serhiy Storchaka4847e4e2014-01-10 13:37:54 +020019 @support.bigmemtest(size=support._2G + 100, memuse=1, dry_run=False)
Victor Stinnerb3c9e072011-01-04 02:07:34 +000020 def test_length_overflow(self, size):
Victor Stinnerb3c9e072011-01-04 02:07:34 +000021 data = b'x' * size
22 parser = cET.XMLParser()
23 try:
24 self.assertRaises(OverflowError, parser.feed, data)
25 finally:
26 data = None
27
Serhiy Storchakab6aa5372015-11-23 08:42:25 +020028 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
Serhiy Storchaka18f018c2016-12-21 12:32:56 +020060 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
Victor Stinnere727d412017-09-18 05:29:37 -070069 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
Oren Milman39ecb9c2017-10-10 23:26:24 +030089 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
Serhiy Storchaka6f906b32018-10-18 09:49:54 +0300121 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
Serhiy Storchakad2a75c62018-12-18 22:29:14 +0200137 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
Eli Bendersky64d11e62012-06-15 07:42:50 +0300157
Eli Bendersky292f9a82012-02-16 19:55:29 +0200158@unittest.skipUnless(cET, 'requires _elementtree')
Eli Bendersky092af1f2012-03-04 07:14:03 +0200159class 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')
Eli Bendersky092af1f2012-03-04 07:14:03 +0200164
Eli Bendersky64d11e62012-06-15 07:42:50 +0300165
Eli Bendersky092af1f2012-03-04 07:14:03 +0200166@unittest.skipUnless(cET, 'requires _elementtree')
Eli Benderskye26fa1b2013-05-19 17:49:54 -0700167@support.cpython_only
Eli Benderskyda578192012-02-16 06:52:39 +0200168class TestAcceleratorImported(unittest.TestCase):
169 # Test that the C accelerator was imported, as expected
170 def test_correct_import_cET(self):
Eli Benderskye26fa1b2013-05-19 17:49:54 -0700171 # SubElement is a function so it retains _elementtree as its module.
Eli Bendersky092af1f2012-03-04 07:14:03 +0200172 self.assertEqual(cET.SubElement.__module__, '_elementtree')
Eli Benderskyda578192012-02-16 06:52:39 +0200173
Florent Xiclunae59a3062012-02-16 23:17:31 +0100174 def test_correct_import_cET_alias(self):
Eli Bendersky092af1f2012-03-04 07:14:03 +0200175 self.assertEqual(cET_alias.SubElement.__module__, '_elementtree')
Florent Xiclunae59a3062012-02-16 23:17:31 +0100176
Eli Benderskye26fa1b2013-05-19 17:49:54 -0700177 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
Victor Stinnerb3c9e072011-01-04 02:07:34 +0000183
Martin v. Löwisbce16662012-06-17 10:41:22 +0200184@unittest.skipUnless(cET, 'requires _elementtree')
Martin v. Löwis2b168442012-07-29 16:38:45 +0200185@support.cpython_only
Martin v. Löwisbce16662012-06-17 10:41:22 +0200186class SizeofTest(unittest.TestCase):
187 def setUp(self):
Martin v. Löwis2b168442012-07-29 16:38:45 +0200188 self.elementsize = support.calcobjsize('5P')
Martin v. Löwisbce16662012-06-17 10:41:22 +0200189 # extra
Serhiy Storchaka43036a62015-02-16 23:58:46 +0200190 self.extra = struct.calcsize('PnnP4P')
Martin v. Löwisbce16662012-06-17 10:41:22 +0200191
Martin v. Löwis2b168442012-07-29 16:38:45 +0200192 check_sizeof = support.check_sizeof
193
Martin v. Löwisbce16662012-06-17 10:41:22 +0200194 def test_element(self):
195 e = cET.Element('a')
Martin v. Löwis2b168442012-07-29 16:38:45 +0200196 self.check_sizeof(e, self.elementsize)
Martin v. Löwisbce16662012-06-17 10:41:22 +0200197
198 def test_element_with_attrib(self):
199 e = cET.Element('a', href='about:')
Martin v. Löwis2b168442012-07-29 16:38:45 +0200200 self.check_sizeof(e, self.elementsize + self.extra)
Martin v. Löwisbce16662012-06-17 10:41:22 +0200201
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
Martin v. Löwis2b168442012-07-29 16:38:45 +0200207 self.check_sizeof(e, self.elementsize + self.extra +
208 struct.calcsize('8P'))
Martin v. Löwisbce16662012-06-17 10:41:22 +0200209
Fredrik Lundh9235ea42005-12-15 18:41:22 +0000210def test_main():
Serhiy Storchakae437a102016-04-24 21:41:02 +0300211 from test import test_xml_etree
Florent Xiclunaf15351d2010-03-13 23:24:31 +0000212
213 # Run the tests specific to the C implementation
Eli Bendersky092af1f2012-03-04 07:14:03 +0200214 support.run_unittest(
215 MiscTests,
216 TestAliasWorking,
Martin v. Löwisbce16662012-06-17 10:41:22 +0200217 TestAcceleratorImported,
218 SizeofTest,
Eli Bendersky092af1f2012-03-04 07:14:03 +0200219 )
Victor Stinnerb3c9e072011-01-04 02:07:34 +0000220
Florent Xiclunaa72a98f2012-02-13 11:03:30 +0100221 # Run the same test suite as the Python module
222 test_xml_etree.test_main(module=cET)
Eli Bendersky092af1f2012-03-04 07:14:03 +0200223
Florent Xiclunaf15351d2010-03-13 23:24:31 +0000224
Fredrik Lundh9235ea42005-12-15 18:41:22 +0000225if __name__ == '__main__':
226 test_main()