port: advance VC6 typeobject frontier and preserve regression coverage
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compile the exact odict_or as C89 and exercise its operation ordering."""
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1]).read_text()
|
||||
match = re.search(
|
||||
r"static PyObject \*\nodict_or\(PyObject \*left, PyObject \*right\)\n\{.*?\n\}",
|
||||
source, re.S,
|
||||
)
|
||||
assert match, "odict_or definition not found"
|
||||
harness = r'''
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
typedef struct { int ordered; int dict; } PyObject;
|
||||
typedef PyObject PyTypeObject;
|
||||
static PyObject left_obj, right_obj, result_obj, not_implemented;
|
||||
static PyObject *expected_type;
|
||||
static int stage, fail_call, fail_update;
|
||||
static int PyODict_Check(PyObject *obj) {
|
||||
assert(stage == 0 && obj == &left_obj);
|
||||
stage = 1;
|
||||
return obj->ordered;
|
||||
}
|
||||
static PyTypeObject *Py_TYPE(PyObject *obj) {
|
||||
assert(stage == 1 && obj == expected_type);
|
||||
stage = 2;
|
||||
return obj;
|
||||
}
|
||||
static int PyDict_Check(PyObject *obj) {
|
||||
assert(stage == 2);
|
||||
assert(obj == (left_obj.ordered ? &right_obj : &left_obj));
|
||||
stage = 3;
|
||||
return obj->dict;
|
||||
}
|
||||
#define Py_RETURN_NOTIMPLEMENTED return ¬_implemented
|
||||
static PyObject *PyObject_CallOneArg(PyObject *type, PyObject *arg) {
|
||||
assert(stage == 3 && type == expected_type && arg == &left_obj);
|
||||
stage = 4;
|
||||
return fail_call ? NULL : &result_obj;
|
||||
}
|
||||
static int mutablemapping_update_arg(PyObject *obj, PyObject *arg) {
|
||||
assert(stage == 4 && obj == &result_obj && arg == &right_obj);
|
||||
stage = 5;
|
||||
return fail_update ? -1 : 0;
|
||||
}
|
||||
static void Py_DECREF(PyObject *obj) {
|
||||
assert(stage == 5 && fail_update && obj == &result_obj);
|
||||
stage = 6;
|
||||
}
|
||||
'''
|
||||
harness += match.group(0)
|
||||
harness += r'''
|
||||
int main(void) {
|
||||
int ordered, scenario;
|
||||
PyObject *result;
|
||||
for (ordered = 0; ordered < 2; ++ordered) {
|
||||
for (scenario = 0; scenario < 4; ++scenario) {
|
||||
left_obj.ordered = ordered;
|
||||
right_obj.ordered = 1;
|
||||
left_obj.dict = right_obj.dict = scenario != 0;
|
||||
expected_type = ordered ? &left_obj : &right_obj;
|
||||
fail_call = scenario == 1;
|
||||
fail_update = scenario == 2;
|
||||
stage = 0;
|
||||
result = odict_or(&left_obj, &right_obj);
|
||||
if (scenario == 0) {
|
||||
assert(result == ¬_implemented && stage == 3);
|
||||
} else if (scenario == 1) {
|
||||
assert(result == NULL && stage == 4);
|
||||
} else if (scenario == 2) {
|
||||
assert(result == NULL && stage == 6);
|
||||
} else {
|
||||
assert(result == &result_obj && stage == 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
with tempfile.TemporaryDirectory(prefix="vc6-odict-or-") as directory:
|
||||
path = Path(directory)
|
||||
(path / "test.c").write_text(harness)
|
||||
compiled = subprocess.run([
|
||||
"cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror",
|
||||
str(path / "test.c"), "-o", str(path / "test"),
|
||||
])
|
||||
if compiled.returncode:
|
||||
sys.exit(compiled.returncode)
|
||||
subprocess.run([str(path / "test")], check=True)
|
||||
print("odict_or C89 compile and operand/rejection/construction/update/cleanup order: PASS (8 cases)")
|
||||
Reference in New Issue
Block a user