port: advance VC6 typeobject frontier and preserve regression coverage
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check only update_arg's first declaration frontier, before later blockers."""
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1]).read_text()
|
||||
match = re.search(
|
||||
r"static int\nmutablemapping_update_arg\(PyObject \*self, PyObject \*arg\)\n\{"
|
||||
r".*?(?= if \(func != NULL\) \{)", source, re.S,
|
||||
)
|
||||
assert match, "mutablemapping_update_arg prefix not found"
|
||||
# Compile the untouched prefix only: iterator/key declarations farther down
|
||||
# are independent frontier defects. The synthetic tail observes lookup output.
|
||||
harness = r'''
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
typedef struct { int unused; } PyObject;
|
||||
static PyObject self_obj, arg_obj, items_obj, func_obj;
|
||||
static int scenario, stage, keys;
|
||||
#define _Py_ID(name) name
|
||||
static int PyDict_CheckExact(PyObject *arg) {
|
||||
assert(stage == 0 && arg == &arg_obj);
|
||||
stage = 1;
|
||||
return scenario < 3;
|
||||
}
|
||||
static PyObject *PyDict_Items(PyObject *arg) {
|
||||
assert(stage == 1 && arg == &arg_obj);
|
||||
stage = 2;
|
||||
return scenario == 0 ? NULL : &items_obj;
|
||||
}
|
||||
static int mutablemapping_add_pairs(PyObject *self, PyObject *items) {
|
||||
assert(stage == 2 && self == &self_obj && items == &items_obj);
|
||||
stage = 3;
|
||||
return scenario == 1 ? -1 : 0;
|
||||
}
|
||||
static void Py_DECREF(PyObject *obj) {
|
||||
assert(stage == 3 && obj == &items_obj);
|
||||
stage = 4;
|
||||
}
|
||||
static int _PyObject_LookupAttr(PyObject *arg, int *id, PyObject **func) {
|
||||
assert(stage == 1 && arg == &arg_obj && id == &keys);
|
||||
stage = 5;
|
||||
*func = scenario == 5 ? &func_obj : NULL;
|
||||
return scenario == 3 ? -1 : scenario == 5;
|
||||
}
|
||||
'''
|
||||
harness += match.group(0)
|
||||
harness += r'''
|
||||
assert(stage == 5 && res == 0);
|
||||
assert(func == (scenario == 5 ? &func_obj : NULL));
|
||||
stage = 6;
|
||||
return 0;
|
||||
}
|
||||
int main(void) {
|
||||
int result;
|
||||
for (scenario = 0; scenario < 6; ++scenario) {
|
||||
stage = 0;
|
||||
result = mutablemapping_update_arg(&self_obj, &arg_obj);
|
||||
assert(result == ((scenario < 2 || scenario == 3) ? -1 : 0));
|
||||
assert(stage == (scenario == 0 ? 2 : scenario < 3 ? 4 :
|
||||
scenario == 3 ? 5 : 6));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
with tempfile.TemporaryDirectory(prefix="vc6-odict-update-arg-func-") as directory:
|
||||
path = Path(directory)
|
||||
(path / "test.c").write_text(harness)
|
||||
result = subprocess.run([
|
||||
"cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror",
|
||||
str(path / "test.c"), "-o", str(path / "test"),
|
||||
])
|
||||
if result.returncode:
|
||||
sys.exit(result.returncode)
|
||||
subprocess.run([str(path / "test")], check=True)
|
||||
print("mutablemapping_update_arg prefix C89 compile and dict/lookup ordering: PASS (6 cases)")
|
||||
Reference in New Issue
Block a user