Skip to content

Commit d400238

Browse files
committed
gh-93649: Split _testcapimodule.c into smaller files
* Move many functions from _testcapimodule.c into more specific files in Modules/_testcapi/. * Add files: * Modules/_testcapi/frame.c * Modules/_testcapi/function.c * Modules/_testcapi/type.c * In moved code: * Replace get_testerror() with PyExc_AssertionError. * Replace raiseTestError() with PyErr_Format(PyExc_AssertionError, ...).
1 parent 379ab85 commit d400238

File tree

15 files changed

+1278
-1209
lines changed

15 files changed

+1278
-1209
lines changed

Lib/test/test_capi/test_misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ def check_negative_refcount(self, code):
409409
code = textwrap.dedent(code)
410410
rc, out, err = assert_python_failure('-c', code)
411411
self.assertRegex(err,
412-
br'_testcapimodule\.c:[0-9]+: '
412+
br'object\.c:[0-9]+: '
413413
br'_Py_NegativeRefcount: Assertion failed: '
414414
br'object has negative ref count')
415415

Modules/Setup.stdlib.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
163163
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
164164
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
165-
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/monitoring.c _testcapi/config.c
165+
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/monitoring.c _testcapi/config.c _testcapi/type.c _testcapi/frame.c _testcapi/function.c
166166
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c
167167
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
168168
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

Modules/_testcapi/dict.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,82 @@
11
#include "parts.h"
22
#include "util.h"
33

4+
5+
static int
6+
test_dict_inner(PyObject *self, int count)
7+
{
8+
Py_ssize_t pos = 0, iterations = 0;
9+
int i;
10+
PyObject *dict = PyDict_New();
11+
PyObject *v, *k;
12+
13+
if (dict == NULL)
14+
return -1;
15+
16+
for (i = 0; i < count; i++) {
17+
v = PyLong_FromLong(i);
18+
if (v == NULL) {
19+
goto error;
20+
}
21+
if (PyDict_SetItem(dict, v, v) < 0) {
22+
Py_DECREF(v);
23+
goto error;
24+
}
25+
Py_DECREF(v);
26+
}
27+
28+
k = v = UNINITIALIZED_PTR;
29+
while (PyDict_Next(dict, &pos, &k, &v)) {
30+
PyObject *o;
31+
iterations++;
32+
33+
assert(k != UNINITIALIZED_PTR);
34+
assert(v != UNINITIALIZED_PTR);
35+
i = PyLong_AS_LONG(v) + 1;
36+
o = PyLong_FromLong(i);
37+
if (o == NULL) {
38+
goto error;
39+
}
40+
if (PyDict_SetItem(dict, k, o) < 0) {
41+
Py_DECREF(o);
42+
goto error;
43+
}
44+
Py_DECREF(o);
45+
k = v = UNINITIALIZED_PTR;
46+
}
47+
assert(k == UNINITIALIZED_PTR);
48+
assert(v == UNINITIALIZED_PTR);
49+
50+
Py_DECREF(dict);
51+
52+
if (iterations != count) {
53+
PyErr_SetString(
54+
PyExc_AssertionError,
55+
"test_dict_iteration: dict iteration went wrong ");
56+
return -1;
57+
} else {
58+
return 0;
59+
}
60+
error:
61+
Py_DECREF(dict);
62+
return -1;
63+
}
64+
65+
static PyObject*
66+
test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored))
67+
{
68+
int i;
69+
70+
for (i = 0; i < 200; i++) {
71+
if (test_dict_inner(self, i) < 0) {
72+
return NULL;
73+
}
74+
}
75+
76+
Py_RETURN_NONE;
77+
}
78+
79+
480
static PyObject *
581
dict_containsstring(PyObject *self, PyObject *args)
682
{
@@ -182,6 +258,7 @@ dict_popstring_null(PyObject *self, PyObject *args)
182258
}
183259

184260
static PyMethodDef test_methods[] = {
261+
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
185262
{"dict_containsstring", dict_containsstring, METH_VARARGS},
186263
{"dict_getitemref", dict_getitemref, METH_VARARGS},
187264
{"dict_getitemstringref", dict_getitemstringref, METH_VARARGS},

Modules/_testcapi/float.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,63 @@
66
#include "clinic/float.c.h"
77

88

9+
/* Test PyOS_string_to_double. */
10+
static PyObject *
11+
test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored))
12+
{
13+
double result;
14+
const char *msg;
15+
16+
#define CHECK_STRING(STR, expected) \
17+
do { \
18+
result = PyOS_string_to_double(STR, NULL, NULL); \
19+
if (result == -1.0 && PyErr_Occurred()) { \
20+
return NULL; \
21+
} \
22+
if (result != (double)expected) { \
23+
msg = "conversion of " STR " to float failed"; \
24+
goto fail; \
25+
} \
26+
} while (0)
27+
28+
#define CHECK_INVALID(STR) \
29+
do { \
30+
result = PyOS_string_to_double(STR, NULL, NULL); \
31+
if (result == -1.0 && PyErr_Occurred()) { \
32+
if (PyErr_ExceptionMatches(PyExc_ValueError)) { \
33+
PyErr_Clear(); \
34+
} \
35+
else { \
36+
return NULL; \
37+
} \
38+
} \
39+
else { \
40+
msg = "conversion of " STR " didn't raise ValueError"; \
41+
goto fail; \
42+
} \
43+
} while (0)
44+
45+
CHECK_STRING("0.1", 0.1);
46+
CHECK_STRING("1.234", 1.234);
47+
CHECK_STRING("-1.35", -1.35);
48+
CHECK_STRING(".1e01", 1.0);
49+
CHECK_STRING("2.e-2", 0.02);
50+
51+
CHECK_INVALID(" 0.1");
52+
CHECK_INVALID("\t\n-3");
53+
CHECK_INVALID(".123 ");
54+
CHECK_INVALID("3\n");
55+
CHECK_INVALID("123abc");
56+
57+
Py_RETURN_NONE;
58+
fail:
59+
PyErr_Format(PyExc_AssertionError, "test_string_to_double: %s", msg);
60+
return NULL;
61+
#undef CHECK_STRING
62+
#undef CHECK_INVALID
63+
}
64+
65+
966
/*[clinic input]
1067
module _testcapi
1168
[clinic start generated code]*/
@@ -100,6 +157,7 @@ _testcapi_float_unpack_impl(PyObject *module, const char *data,
100157
}
101158

102159
static PyMethodDef test_methods[] = {
160+
{"test_string_to_double", test_string_to_double, METH_NOARGS},
103161
_TESTCAPI_FLOAT_PACK_METHODDEF
104162
_TESTCAPI_FLOAT_UNPACK_METHODDEF
105163
{NULL},

Modules/_testcapi/frame.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#include "parts.h"
2+
#include "util.h"
3+
4+
#include "frameobject.h" // PyFrame_New()
5+
6+
7+
static PyObject *
8+
frame_getlocals(PyObject *self, PyObject *frame)
9+
{
10+
if (!PyFrame_Check(frame)) {
11+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
12+
return NULL;
13+
}
14+
return PyFrame_GetLocals((PyFrameObject *)frame);
15+
}
16+
17+
18+
static PyObject *
19+
frame_getglobals(PyObject *self, PyObject *frame)
20+
{
21+
if (!PyFrame_Check(frame)) {
22+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
23+
return NULL;
24+
}
25+
return PyFrame_GetGlobals((PyFrameObject *)frame);
26+
}
27+
28+
29+
static PyObject *
30+
frame_getgenerator(PyObject *self, PyObject *frame)
31+
{
32+
if (!PyFrame_Check(frame)) {
33+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
34+
return NULL;
35+
}
36+
return PyFrame_GetGenerator((PyFrameObject *)frame);
37+
}
38+
39+
40+
static PyObject *
41+
frame_getbuiltins(PyObject *self, PyObject *frame)
42+
{
43+
if (!PyFrame_Check(frame)) {
44+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
45+
return NULL;
46+
}
47+
return PyFrame_GetBuiltins((PyFrameObject *)frame);
48+
}
49+
50+
51+
static PyObject *
52+
frame_getlasti(PyObject *self, PyObject *frame)
53+
{
54+
if (!PyFrame_Check(frame)) {
55+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
56+
return NULL;
57+
}
58+
int lasti = PyFrame_GetLasti((PyFrameObject *)frame);
59+
if (lasti < 0) {
60+
assert(lasti == -1);
61+
Py_RETURN_NONE;
62+
}
63+
return PyLong_FromLong(lasti);
64+
}
65+
66+
67+
static PyObject *
68+
frame_new(PyObject *self, PyObject *args)
69+
{
70+
PyObject *code, *globals, *locals;
71+
if (!PyArg_ParseTuple(args, "OOO", &code, &globals, &locals)) {
72+
return NULL;
73+
}
74+
if (!PyCode_Check(code)) {
75+
PyErr_SetString(PyExc_TypeError, "argument must be a code object");
76+
return NULL;
77+
}
78+
PyThreadState *tstate = PyThreadState_Get();
79+
80+
return (PyObject *)PyFrame_New(tstate, (PyCodeObject *)code, globals, locals);
81+
}
82+
83+
84+
static PyObject *
85+
frame_getvar(PyObject *self, PyObject *args)
86+
{
87+
PyObject *frame, *name;
88+
if (!PyArg_ParseTuple(args, "OO", &frame, &name)) {
89+
return NULL;
90+
}
91+
if (!PyFrame_Check(frame)) {
92+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
93+
return NULL;
94+
}
95+
96+
return PyFrame_GetVar((PyFrameObject *)frame, name);
97+
}
98+
99+
100+
static PyObject *
101+
frame_getvarstring(PyObject *self, PyObject *args)
102+
{
103+
PyObject *frame;
104+
const char *name;
105+
if (!PyArg_ParseTuple(args, "Oy", &frame, &name)) {
106+
return NULL;
107+
}
108+
if (!PyFrame_Check(frame)) {
109+
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
110+
return NULL;
111+
}
112+
113+
return PyFrame_GetVarString((PyFrameObject *)frame, name);
114+
}
115+
116+
117+
static PyMethodDef test_methods[] = {
118+
{"frame_getlocals", frame_getlocals, METH_O, NULL},
119+
{"frame_getglobals", frame_getglobals, METH_O, NULL},
120+
{"frame_getgenerator", frame_getgenerator, METH_O, NULL},
121+
{"frame_getbuiltins", frame_getbuiltins, METH_O, NULL},
122+
{"frame_getlasti", frame_getlasti, METH_O, NULL},
123+
{"frame_new", frame_new, METH_VARARGS, NULL},
124+
{"frame_getvar", frame_getvar, METH_VARARGS, NULL},
125+
{"frame_getvarstring", frame_getvarstring, METH_VARARGS, NULL},
126+
{NULL},
127+
};
128+
129+
int
130+
_PyTestCapi_Init_Frame(PyObject *m)
131+
{
132+
return PyModule_AddFunctions(m, test_methods);
133+
}
134+

0 commit comments

Comments
 (0)