[Python-checkins] GH-98831: Add some tests for generate_cases.py (#100763)

gvanrossum webhook-mailer at python.org
Fri Jan 6 11:04:27 EST 2023


https://github.com/python/cpython/commit/9ffbc58f5cb6d2b002f8785886588d646af517db
commit: 9ffbc58f5cb6d2b002f8785886588d646af517db
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2023-01-06T08:04:20-08:00
summary:

GH-98831: Add some tests for generate_cases.py (#100763)

- This doesn't cover everything (far from it) but it's a start.
- This uses pytest, which isn't ideal, but was quickest to get started.

Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com>

files:
A Tools/cases_generator/test_generator.py

diff --git a/Tools/cases_generator/test_generator.py b/Tools/cases_generator/test_generator.py
new file mode 100644
index 000000000000..e707a5334268
--- /dev/null
+++ b/Tools/cases_generator/test_generator.py
@@ -0,0 +1,310 @@
+# Sorry for using pytest, these tests are mostly just for me.
+# Use pytest -vv for best results.
+
+import tempfile
+
+import generate_cases
+
+
+def run_cases_test(input: str, expected: str):
+    temp_input = tempfile.NamedTemporaryFile("w+")
+    temp_input.write(generate_cases.BEGIN_MARKER)
+    temp_input.write(input)
+    temp_input.write(generate_cases.END_MARKER)
+    temp_input.flush()
+    temp_output = tempfile.NamedTemporaryFile("w+")
+    a = generate_cases.Analyzer(temp_input.name, temp_output.name)
+    a.parse()
+    a.analyze()
+    if a.errors:
+        raise RuntimeError(f"Found {a.errors} errors")
+    a.write_instructions()
+    temp_output.seek(0)
+    lines = temp_output.readlines()
+    while lines and lines[0].startswith("// "):
+        lines.pop(0)
+    actual = "".join(lines)
+    assert actual.rstrip() == expected.rstrip()
+
+def test_legacy():
+    input = """
+        inst(OP) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            spam();
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_inst_no_args():
+    input = """
+        inst(OP, (--)) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            spam();
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_inst_one_pop():
+    input = """
+        inst(OP, (value --)) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *value = PEEK(1);
+            spam();
+            STACK_SHRINK(1);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_inst_one_push():
+    input = """
+        inst(OP, (-- res)) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *res;
+            spam();
+            STACK_GROW(1);
+            POKE(1, res);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_inst_one_push_one_pop():
+    input = """
+        inst(OP, (value -- res)) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *value = PEEK(1);
+            PyObject *res;
+            spam();
+            POKE(1, res);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_binary_op():
+    input = """
+        inst(OP, (left, right -- res)) {
+            spam();
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *right = PEEK(1);
+            PyObject *left = PEEK(2);
+            PyObject *res;
+            spam();
+            STACK_SHRINK(1);
+            POKE(1, res);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_predictions():
+    input = """
+        inst(OP1, (--)) {
+        }
+        inst(OP2, (--)) {
+        }
+        inst(OP3, (--)) {
+            DEOPT_IF(xxx, OP1);
+            PREDICT(OP2);
+        }
+    """
+    output = """
+        TARGET(OP1) {
+            PREDICTED(OP1);
+            DISPATCH();
+        }
+
+        TARGET(OP2) {
+            PREDICTED(OP2);
+            DISPATCH();
+        }
+
+        TARGET(OP3) {
+            DEOPT_IF(xxx, OP1);
+            PREDICT(OP2);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_error_if_plain():
+    input = """
+        inst(OP, (--)) {
+            ERROR_IF(cond, label);
+        }
+    """
+    output = """
+        TARGET(OP) {
+            if (cond) goto label;
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_error_if_pop():
+    input = """
+        inst(OP, (left, right -- res)) {
+            ERROR_IF(cond, label);
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *right = PEEK(1);
+            PyObject *left = PEEK(2);
+            PyObject *res;
+            if (cond) goto pop_2_label;
+            STACK_SHRINK(1);
+            POKE(1, res);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_cache_effect():
+    input = """
+        inst(OP, (counter/1, extra/2, value --)) {
+        }
+    """
+    output = """
+        TARGET(OP) {
+            PyObject *value = PEEK(1);
+            uint16_t counter = read_u16(&next_instr[0].cache);
+            uint32_t extra = read_u32(&next_instr[1].cache);
+            STACK_SHRINK(1);
+            JUMPBY(3);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_suppress_dispatch():
+    input = """
+        inst(OP, (--)) {
+            goto somewhere;
+        }
+    """
+    output = """
+        TARGET(OP) {
+            goto somewhere;
+        }
+    """
+    run_cases_test(input, output)
+
+def test_super_instruction():
+    # TODO: Test cache effect
+    input = """
+        inst(OP1, (counter/1, arg --)) {
+            op1();
+        }
+        inst(OP2, (extra/2, arg --)) {
+            op2();
+        }
+        super(OP) = OP1 + OP2;
+    """
+    output = """
+        TARGET(OP1) {
+            PyObject *arg = PEEK(1);
+            uint16_t counter = read_u16(&next_instr[0].cache);
+            op1();
+            STACK_SHRINK(1);
+            JUMPBY(1);
+            DISPATCH();
+        }
+
+        TARGET(OP2) {
+            PyObject *arg = PEEK(1);
+            uint32_t extra = read_u32(&next_instr[0].cache);
+            op2();
+            STACK_SHRINK(1);
+            JUMPBY(2);
+            DISPATCH();
+        }
+
+        TARGET(OP) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *arg = _tmp_1;
+                uint16_t counter = read_u16(&next_instr[0].cache);
+                op1();
+            }
+            JUMPBY(1);
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *arg = _tmp_2;
+                uint32_t extra = read_u32(&next_instr[0].cache);
+                op2();
+            }
+            JUMPBY(2);
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)
+
+def test_macro_instruction():
+    input = """
+        inst(OP1, (counter/1, arg --)) {
+            op1();
+        }
+        op(OP2, (extra/2, arg --)) {
+            op2();
+        }
+        macro(OP) = OP1 + cache/2 + OP2;
+    """
+    output = """
+        TARGET(OP1) {
+            PyObject *arg = PEEK(1);
+            uint16_t counter = read_u16(&next_instr[0].cache);
+            op1();
+            STACK_SHRINK(1);
+            JUMPBY(1);
+            DISPATCH();
+        }
+
+        TARGET(OP) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *arg = _tmp_1;
+                uint16_t counter = read_u16(&next_instr[0].cache);
+                op1();
+            }
+            {
+                PyObject *arg = _tmp_2;
+                uint32_t extra = read_u32(&next_instr[3].cache);
+                op2();
+            }
+            JUMPBY(5);
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+    """
+    run_cases_test(input, output)



More information about the Python-checkins mailing list