Skip to content

Commit aa67427

Browse files
Add tests in cases generator
1 parent 34dd801 commit aa67427

File tree

3 files changed

+276
-105
lines changed

3 files changed

+276
-105
lines changed

Lib/test/test_generated_cases.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import tempfile
66
import unittest
7+
import textwrap
78

89
from io import StringIO
910
from test import support
@@ -36,6 +37,7 @@ def skip_if_different_mount_drives():
3637
import parser
3738
from stack import Local, Stack
3839
import tier1_generator
40+
import tier1_tail_call_generator
3941
import opcode_metadata_generator
4042
import optimizer_generator
4143

@@ -1714,6 +1716,156 @@ def test_pop_dead_inputs_with_output(self):
17141716
self.run_cases_test(input, output)
17151717

17161718

1719+
class TestGeneratedTailCallErorHandlers(unittest.TestCase):
1720+
def setUp(self) -> None:
1721+
super().setUp()
1722+
self.maxDiff = None
1723+
1724+
self.temp_dir = tempfile.gettempdir()
1725+
self.temp_input_filename = os.path.join(self.temp_dir, "input.txt")
1726+
self.temp_output_filename = os.path.join(self.temp_dir, "output.txt")
1727+
self.temp_metadata_filename = os.path.join(self.temp_dir, "metadata.txt")
1728+
self.temp_pymetadata_filename = os.path.join(self.temp_dir, "pymetadata.txt")
1729+
self.temp_executor_filename = os.path.join(self.temp_dir, "executor.txt")
1730+
1731+
def tearDown(self) -> None:
1732+
for filename in [
1733+
self.temp_input_filename,
1734+
self.temp_output_filename,
1735+
self.temp_metadata_filename,
1736+
self.temp_pymetadata_filename,
1737+
self.temp_executor_filename,
1738+
]:
1739+
try:
1740+
os.remove(filename)
1741+
except:
1742+
pass
1743+
super().tearDown()
1744+
1745+
def run_cases_test(self, input: str, expected: str):
1746+
with open(self.temp_input_filename, "w+") as temp_input:
1747+
temp_input.write(textwrap.dedent(input))
1748+
temp_input.flush()
1749+
1750+
with handle_stderr():
1751+
tier1_tail_call_generator.generate_label_handlers_from_files(
1752+
self.temp_input_filename, self.temp_output_filename
1753+
)
1754+
1755+
with open(self.temp_output_filename) as temp_output:
1756+
lines = temp_output.readlines()
1757+
while lines and lines[0].startswith(("// ", "#", " #", "\n")):
1758+
lines.pop(0)
1759+
while lines and lines[-1].startswith(("#", "\n")):
1760+
lines.pop(-1)
1761+
actual = "".join(lines)
1762+
1763+
self.assertEqual(actual.strip(), textwrap.dedent(expected).strip())
1764+
1765+
def test_correctly_finds_pyeval_framedefault(self):
1766+
input = """
1767+
PyObject* _Py_HOT_FUNCTION
1768+
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
1769+
{
1770+
1771+
/* END_BASE_INTERPRETER */
1772+
}
1773+
"""
1774+
output = """
1775+
"""
1776+
self.run_cases_test(input, output)
1777+
1778+
def test_simple_label(self):
1779+
input = """
1780+
PyObject* _Py_HOT_FUNCTION
1781+
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
1782+
{
1783+
1784+
TAIL_CALL_TARGET(error):
1785+
DO_THING();
1786+
/* END_BASE_INTERPRETER */
1787+
}
1788+
"""
1789+
output = """
1790+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
1791+
1792+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
1793+
{
1794+
DO_THING();
1795+
/* END_BASE_INTERPRETER */
1796+
}
1797+
"""
1798+
self.run_cases_test(input, output)
1799+
1800+
def test_fallthrough_label(self):
1801+
input = """
1802+
PyObject* _Py_HOT_FUNCTION
1803+
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
1804+
{
1805+
1806+
TAIL_CALL_TARGET(error):
1807+
DO_THING();
1808+
TAIL_CALL_TARGET(fallthrough):
1809+
DO_THING2();
1810+
/* END_BASE_INTERPRETER */
1811+
}
1812+
"""
1813+
output = """
1814+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
1815+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS);
1816+
1817+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
1818+
{
1819+
DO_THING();
1820+
CEVAL_GOTO(fallthrough);
1821+
}
1822+
1823+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS)
1824+
{
1825+
DO_THING2();
1826+
/* END_BASE_INTERPRETER */
1827+
}
1828+
"""
1829+
self.run_cases_test(input, output)
1830+
1831+
def test_transform_gotos(self):
1832+
input = """
1833+
PyObject* _Py_HOT_FUNCTION
1834+
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
1835+
{
1836+
1837+
TAIL_CALL_TARGET(error):
1838+
if (thing) {
1839+
goto fallthrough;
1840+
}
1841+
DO_THING();
1842+
TAIL_CALL_TARGET(fallthrough):
1843+
DO_THING2();
1844+
/* END_BASE_INTERPRETER */
1845+
}
1846+
"""
1847+
output = """
1848+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
1849+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS);
1850+
1851+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
1852+
{
1853+
if (thing) {
1854+
CEVAL_GOTO(fallthrough);
1855+
}
1856+
DO_THING();
1857+
CEVAL_GOTO(fallthrough);
1858+
}
1859+
1860+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS)
1861+
{
1862+
DO_THING2();
1863+
/* END_BASE_INTERPRETER */
1864+
}
1865+
"""
1866+
self.run_cases_test(input, output)
1867+
1868+
17171869
class TestGeneratedAbstractCases(unittest.TestCase):
17181870
def setUp(self) -> None:
17191871
super().setUp()

0 commit comments

Comments
 (0)