Skip to content

Commit 62a1a4f

Browse files
Add tests
1 parent 2694800 commit 62a1a4f

File tree

3 files changed

+362
-229
lines changed

3 files changed

+362
-229
lines changed

Lib/test/test_generated_cases.py

+123
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,129 @@ def test_multiple_labels(self):
18171817
}
18181818
"""
18191819

1820+
class TestGeneratedTailCallHandlers(unittest.TestCase):
1821+
def setUp(self) -> None:
1822+
super().setUp()
1823+
self.maxDiff = None
1824+
1825+
self.temp_dir = tempfile.gettempdir()
1826+
self.temp_input_filename = os.path.join(self.temp_dir, "input.txt")
1827+
self.temp_output_filename = os.path.join(self.temp_dir, "output.txt")
1828+
self.temp_labels_output_filename = os.path.join(self.temp_dir, "labels_output.txt")
1829+
1830+
def tearDown(self) -> None:
1831+
for filename in [
1832+
self.temp_input_filename,
1833+
self.temp_output_filename,
1834+
self.temp_labels_output_filename,
1835+
]:
1836+
try:
1837+
os.remove(filename)
1838+
except Exception:
1839+
pass
1840+
super().tearDown()
1841+
1842+
def run_cases_test(self, input: str, expected: str, expected_labels: str):
1843+
with open(self.temp_input_filename, "w+") as temp_input:
1844+
temp_input.write(parser.BEGIN_MARKER)
1845+
temp_input.write(input)
1846+
temp_input.write(parser.END_MARKER)
1847+
temp_input.flush()
1848+
1849+
with handle_stderr():
1850+
tier1_tail_call_generator.generate_tier1_from_files(
1851+
[self.temp_input_filename], self.temp_output_filename, self.temp_labels_output_filename, False
1852+
)
1853+
1854+
with open(self.temp_output_filename) as temp_output:
1855+
lines = temp_output.read()
1856+
_, rest = lines.split(tier1_generator.INSTRUCTION_START_MARKER)
1857+
instructions, _ = rest.split(tier1_generator.INSTRUCTION_END_MARKER)
1858+
1859+
with open(self.temp_labels_output_filename) as temp_output:
1860+
lines = temp_output.readlines()
1861+
while lines and lines[0].startswith(("// ", "#", " #", "\n")):
1862+
lines.pop(0)
1863+
while lines and lines[-1].startswith(("#", "\n")):
1864+
lines.pop(-1)
1865+
actual_labels = "".join(lines)
1866+
1867+
self.assertEqual(instructions.strip(), expected.strip())
1868+
self.assertEqual(actual_labels.strip(), expected_labels.strip())
1869+
1870+
def test_basic(self):
1871+
input = """
1872+
inst(OP, (--)) {
1873+
SPAM();
1874+
}
1875+
"""
1876+
output = """
1877+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_OP(TAIL_CALL_PARAMS) {
1878+
{
1879+
frame->instr_ptr = next_instr;
1880+
next_instr += 1;
1881+
INSTRUCTION_STATS(OP);
1882+
SPAM();
1883+
}
1884+
DISPATCH();
1885+
}
1886+
"""
1887+
output_labels = ""
1888+
self.run_cases_test(input, output, output_labels)
1889+
1890+
def test_label_transformed(self):
1891+
"""This tests that the labels and their gotos/DISPATCH get transformed to tail calls in the
1892+
tail-calling interpreter, while staying the same/becoming an entry call in the normal interpreter.
1893+
"""
1894+
input = """
1895+
inst(OP, (--)) {
1896+
SPAM();
1897+
}
1898+
1899+
label(hello) {
1900+
EGGS();
1901+
if (x) {
1902+
goto baz;
1903+
}
1904+
DISPATCH();
1905+
}
1906+
"""
1907+
output = """
1908+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_hello(TAIL_CALL_PARAMS)
1909+
{
1910+
EGGS();
1911+
if (x) {
1912+
TAIL_CALL(baz);
1913+
}
1914+
DISPATCH();
1915+
}
1916+
1917+
1918+
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_OP(TAIL_CALL_PARAMS) {
1919+
{
1920+
frame->instr_ptr = next_instr;
1921+
next_instr += 1;
1922+
INSTRUCTION_STATS(OP);
1923+
SPAM();
1924+
}
1925+
DISPATCH();
1926+
hello:
1927+
TAIL_CALL(hello);
1928+
}
1929+
"""
1930+
output_labels = """
1931+
hello:
1932+
{
1933+
EGGS();
1934+
if (x) {
1935+
goto baz;
1936+
}
1937+
return _TAIL_CALL_entry(frame, stack_pointer, tstate, next_instr, 0, 0);
1938+
}
1939+
"""
1940+
self.run_cases_test(input, output, output_labels)
1941+
1942+
18201943
class TestGeneratedAbstractCases(unittest.TestCase):
18211944
def setUp(self) -> None:
18221945
super().setUp()

0 commit comments

Comments
 (0)