Files
Python3-Win9x/scripts/vc6-picklebuf-raw-c89.test.py
T

112 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""Compile the exact picklebuf_raw body as C89 and check its error order."""
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 \*\npicklebuf_raw\([^\n]+\)\n\{.*?\n\}", source, re.S
)
assert match, "picklebuf_raw not found"
harness = r'''
#include <assert.h>
#include <stddef.h>
#include <string.h>
typedef struct { int unused; } PyObject;
typedef struct {
PyObject *obj;
long *suboffsets;
const char *format;
int ndim;
long itemsize, len;
long *shape, *strides;
} Py_buffer;
typedef struct { Py_buffer view; } PyPickleBufferObject;
typedef struct { Py_buffer view; int flags; } PyMemoryViewObject;
#define Py_UNUSED(name) name
#define _Py_MEMORYVIEW_C 1
#define _Py_MEMORYVIEW_FORTRAN 2
static int PyExc_ValueError = 1, PyExc_BufferError = 2;
static int scenario;
static char events[16];
static PyPickleBufferObject self;
static PyMemoryViewObject memory;
static PyObject base;
static void event(char c) {
size_t n = strlen(events);
assert(n + 1 < sizeof(events));
events[n] = c; events[n + 1] = '\0';
}
static void PyErr_SetString(int exc, const char *message) {
assert(exc == (scenario == 0 ? PyExc_ValueError : PyExc_BufferError));
assert(strcmp(message, scenario == 0
? "operation forbidden on released PickleBuffer object"
: "cannot extract raw buffer from non-contiguous buffer") == 0);
event('E');
}
static int PyBuffer_IsContiguous(Py_buffer *view, char order) {
assert(view == &self.view && order == 'A'); event('C');
return scenario != 2;
}
static PyObject *PyMemoryView_FromObject(PyObject *obj) {
assert(obj == (PyObject *)&self); event('M');
return scenario == 3 ? NULL : (PyObject *)&memory;
}
'''
harness += match.group(0)
harness += r'''
int main(void) {
static const char *expected[] = {"E", "E", "CE", "CM", "CM"};
PyObject *result;
PyMemoryViewObject before;
Py_buffer original;
long offset = 0;
for (scenario = 0; scenario < 5; ++scenario) {
memset(&memory, 0, sizeof(memory));
memory.view.obj = &base;
memory.view.format = "i";
memory.view.ndim = 2;
memory.view.itemsize = 4;
memory.view.len = 24;
memory.flags = 8;
memcpy(&before, &memory, sizeof(memory));
self.view = memory.view;
self.view.obj = scenario == 0 ? NULL : &base;
self.view.suboffsets = scenario == 1 ? &offset : NULL;
memcpy(&original, &self.view, sizeof(original));
events[0] = '\0';
result = picklebuf_raw(&self, NULL);
assert(strcmp(events, expected[scenario]) == 0);
assert(memcmp(&original, &self.view, sizeof(original)) == 0);
if (scenario < 4) {
assert(result == NULL);
assert(memcmp(&before, &memory, sizeof(memory)) == 0);
} else {
assert(result == (PyObject *)&memory);
assert(memory.view.obj == &base && memory.view.len == 24);
assert(memory.view.suboffsets == NULL);
assert(strcmp(memory.view.format, "B") == 0);
assert(memory.view.ndim == 1 && memory.view.itemsize == 1);
assert(memory.view.shape == &memory.view.len);
assert(memory.view.strides == &memory.view.itemsize);
assert(memory.flags == (_Py_MEMORYVIEW_C | _Py_MEMORYVIEW_FORTRAN));
}
}
return 0;
}
'''
with tempfile.TemporaryDirectory(prefix="vc6-picklebuf-raw-") as directory:
path = Path(directory)
(path / "test.c").write_text(harness)
result = subprocess.run([
"cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror",
"-Wno-unused-parameter", str(path / "test.c"), "-o", str(path / "test"),
])
if result.returncode:
sys.exit(result.returncode)
subprocess.run([str(path / "test")], check=True)
print("picklebuf_raw C89 compile and validation/allocation order: PASS (5 cases)")