Skip to content

Commit 7015918

Browse files
committed
add tests for XML_ParseFile
1 parent f75a84c commit 7015918

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

Lib/test/test_pyexpat.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ def test_parse_reentrancy_with_encoding(self, encoding):
281281
# See https://github.com/python/cpython/issues/146169.
282282
parser = expat.ParserCreate(encoding=encoding)
283283

284-
CharacterDataHandler = lambda data: parser.Parse(data, False)
284+
def CharacterDataHandler(data):
285+
return parser.Parse(data, False)
285286
CharacterDataHandler = mock.Mock(wraps=CharacterDataHandler)
286287
def StartElementHandler(name, attrs):
287288
parser.CharacterDataHandler = CharacterDataHandler
@@ -294,6 +295,25 @@ def StartElementHandler(name, attrs):
294295
parser.Parse(payload[i:i+1], i == len(payload) - 1)
295296
CharacterDataHandler.assert_called_once_with("x")
296297

298+
@support.subTests("encoding", ("utf-8", "utf-16"))
299+
def test_parse_file_reentrancy_with_encoding(self, encoding):
300+
# See https://github.com/python/cpython/issues/146169.
301+
parser = expat.ParserCreate(encoding=encoding)
302+
303+
def CharacterDataHandler(data):
304+
return parser.ParseFile(BytesIO(data.encode(encoding)))
305+
CharacterDataHandler = mock.Mock(wraps=CharacterDataHandler)
306+
def StartElementHandler(name, attrs):
307+
parser.CharacterDataHandler = CharacterDataHandler
308+
parser.StartElementHandler = StartElementHandler
309+
310+
payload = "<a>x".encode(encoding)
311+
payload_buffer = BytesIO(payload)
312+
msg = re.escape("cannot call ParseFile() from within a handler")
313+
with self.assertRaisesRegex(RuntimeError, msg):
314+
parser.ParseFile(payload_buffer)
315+
CharacterDataHandler.assert_called_once_with("x")
316+
297317
@support.subTests("encoding", ("utf-8", "utf-16"))
298318
def test_parse_reentrancy_allowed_for_external_parser(self, encoding):
299319
parser = expat.ParserCreate(encoding=encoding)
@@ -322,6 +342,33 @@ def StartElementHandler(*args):
322342
external_ref_args = ('ext', None, 'entity.file', None)
323343
ExternalEntityRefHandler.assert_called_once_with(*external_ref_args)
324344

345+
@support.subTests("encoding", ("utf-8", "utf-16"))
346+
def test_parse_file_reentrancy_allowed_for_external_parser(self, encoding):
347+
parser = expat.ParserCreate(encoding=encoding)
348+
subparser = parser.ExternalEntityParserCreate(None, encoding)
349+
payload_extstr = '<!ENTITY ext SYSTEM "entity.file">'
350+
351+
def ExternalEntityRefHandler(*args):
352+
subparser.ParseFile(BytesIO(payload_extstr.encode(encoding)))
353+
# return a nonzero integer to indicate that parsing continues
354+
return 1
355+
ExternalEntityRefHandler = mock.Mock(wraps=ExternalEntityRefHandler)
356+
357+
def StartElementHandler(*args):
358+
parser.ExternalEntityRefHandler = ExternalEntityRefHandler
359+
parser.StartElementHandler = StartElementHandler
360+
361+
payload = textwrap.dedent(f"""\
362+
<?xml version="1.0" standalone="no"?>
363+
<!DOCTYPE quotations SYSTEM "quotations.dtd" [{payload_extstr}]>
364+
<root>&ext;</root>
365+
""").encode(encoding)
366+
367+
# Check that external parsers be called from parent's handlers.
368+
parser.ParseFile(BytesIO(payload))
369+
external_ref_args = ('ext', None, 'entity.file', None)
370+
ExternalEntityRefHandler.assert_called_once_with(*external_ref_args)
371+
325372

326373
class NamespaceSeparatorTest(unittest.TestCase):
327374
def test_legal(self):

0 commit comments

Comments
 (0)