Skip to content

Commit

Permalink
pythongh-76785: Clean up the Failure-Related _xxsubinterpreters Tests (
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently authored and Glyphack committed Jan 27, 2024
1 parent d3bc968 commit 7d84391
Showing 1 changed file with 157 additions and 37 deletions.
194 changes: 157 additions & 37 deletions Lib/test/test__xxsubinterpreters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import _testinternalcapi
from test import support
from test.support import import_helper
from test.support import os_helper
from test.support import script_helper


Expand Down Expand Up @@ -759,43 +760,6 @@ def test_bytes_for_script(self):
with self.assertRaises(TypeError):
interpreters.run_string(self.id, b'print("spam")')

@contextlib.contextmanager
def assert_run_failed(self, exctype, msg=None):
with self.assertRaises(interpreters.RunFailedError) as caught:
yield
if msg is None:
self.assertEqual(str(caught.exception).split(':')[0],
exctype.__name__)
else:
self.assertEqual(str(caught.exception),
"{}: {}".format(exctype.__name__, msg))

def test_invalid_syntax(self):
with self.assert_run_failed(SyntaxError):
# missing close paren
interpreters.run_string(self.id, 'print("spam"')

def test_failure(self):
with self.assert_run_failed(Exception, 'spam'):
interpreters.run_string(self.id, 'raise Exception("spam")')

def test_SystemExit(self):
with self.assert_run_failed(SystemExit, '42'):
interpreters.run_string(self.id, 'raise SystemExit(42)')

def test_sys_exit(self):
with self.assert_run_failed(SystemExit):
interpreters.run_string(self.id, dedent("""
import sys
sys.exit()
"""))

with self.assert_run_failed(SystemExit, '42'):
interpreters.run_string(self.id, dedent("""
import sys
sys.exit(42)
"""))

def test_with_shared(self):
r, w = os.pipe()

Expand Down Expand Up @@ -959,6 +923,162 @@ def f():
self.assertEqual(retcode, 0)


class RunFailedTests(TestBase):

def setUp(self):
super().setUp()
self.id = interpreters.create()

def add_module(self, modname, text):
import tempfile
tempdir = tempfile.mkdtemp()
self.addCleanup(lambda: os_helper.rmtree(tempdir))
interpreters.run_string(self.id, dedent(f"""
import sys
sys.path.insert(0, {tempdir!r})
"""))
return script_helper.make_script(tempdir, modname, text)

def run_script(self, text, *, fails=False):
excwrapper = interpreters.RunFailedError
r, w = os.pipe()
try:
script = dedent(f"""
import os, sys
os.write({w}, b'0')
# This raises an exception:
{{}}
# Nothing from here down should ever run.
os.write({w}, b'1')
class NeverError(Exception): pass
raise NeverError # never raised
""").format(dedent(text))
if fails:
with self.assertRaises(excwrapper) as caught:
interpreters.run_string(self.id, script)
return caught.exception
else:
interpreters.run_string(self.id, script)
return None
except:
raise # re-raise
else:
msg = os.read(r, 100)
self.assertEqual(msg, b'0')
finally:
os.close(r)
os.close(w)

def _assert_run_failed(self, exctype, msg, script):
if isinstance(exctype, str):
exctype_name = exctype
exctype = None
else:
exctype_name = exctype.__name__

# Run the script.
exc = self.run_script(script, fails=True)

# Check the wrapper exception.
if msg is None:
self.assertEqual(str(exc).split(':')[0],
exctype_name)
else:
self.assertEqual(str(exc),
'{}: {}'.format(exctype_name, msg))

return exc

def assert_run_failed(self, exctype, script):
self._assert_run_failed(exctype, None, script)

def assert_run_failed_msg(self, exctype, msg, script):
self._assert_run_failed(exctype, msg, script)

def test_exit(self):
with self.subTest('sys.exit(0)'):
# XXX Should an unhandled SystemExit(0) be handled as not-an-error?
self.assert_run_failed(SystemExit, """
sys.exit(0)
""")

with self.subTest('sys.exit()'):
self.assert_run_failed(SystemExit, """
import sys
sys.exit()
""")

with self.subTest('sys.exit(42)'):
self.assert_run_failed_msg(SystemExit, '42', """
import sys
sys.exit(42)
""")

with self.subTest('SystemExit'):
self.assert_run_failed_msg(SystemExit, '42', """
raise SystemExit(42)
""")

# XXX Also check os._exit() (via a subprocess)?

def test_plain_exception(self):
self.assert_run_failed_msg(Exception, 'spam', """
raise Exception("spam")
""")

def test_invalid_syntax(self):
script = dedent("""
x = 1 + 2
y = 2 + 4
z = 4 + 8
# missing close paren
print("spam"
if x + y + z < 20:
...
""")

with self.subTest('script'):
self.assert_run_failed(SyntaxError, script)

with self.subTest('module'):
modname = 'spam_spam_spam'
filename = self.add_module(modname, script)
self.assert_run_failed(SyntaxError, f"""
import {modname}
""")

def test_NameError(self):
self.assert_run_failed(NameError, """
res = spam + eggs
""")
# XXX check preserved suggestions

def test_AttributeError(self):
self.assert_run_failed(AttributeError, """
object().spam
""")
# XXX check preserved suggestions

def test_ExceptionGroup(self):
self.assert_run_failed(ExceptionGroup, """
raise ExceptionGroup('exceptions', [
Exception('spam'),
ImportError('eggs'),
])
""")

def test_user_defined_exception(self):
self.assert_run_failed_msg('MyError', 'spam', """
class MyError(Exception):
pass
raise MyError('spam')
""")


class RunFuncTests(TestBase):

def setUp(self):
Expand Down

0 comments on commit 7d84391

Please sign in to comment.