8000 gh-93649: Split _testcapimodule.c into smaller files · python/cpython@78d4204 · GitHub
[go: up one dir, main page]

Skip to content

Commit 78d4204

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 8df5193 commit 78d4204

18 files changed

+1337
-1257
lines changed

Lib/test/test_capi/test_frame.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import sys
2+
import unittest
3+
from test.support import import_helper
4+
5+
6+
_testcapi = import_helper.import_module('_testcapi')
7+
8+
9+
class TestCAPI(unittest.TestCase):
10+
def getframe(self):
11+
return sys._getframe()
12+
13+
def test_frame_getters(self):
14+
frame = self.getframe()
15+
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
16+
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
17+
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
18+
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))
19+
20+
def test_getvar(self):
21+
current_frame = sys._getframe()
22+
x = 1
23+
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
24+
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
25+
with self.assertRaises(NameError):
26+
_testcapi.frame_getvar(current_frame, "y")
27+
with self.assertRaises(NameError):
28+
_testcapi.frame_getvarstring(current_frame, b"y")
29+
30+
# wrong name type
31+
with self.assertRaises(TypeError):
32+
_testcapi.frame_getvar(current_frame, b'x')
33+
with self.assertRaises(TypeError):
34+
_testcapi.frame_getvar(current_frame, 123)
35+
36+
def getgenframe(self):
37+
yield sys._getframe()
38+
39+
def test_frame_get_generator(self):
40+
gen = self.getgenframe()
41+
frame = next(gen)
42+
self.assertIs(gen, _testcapi.frame_getgenerator(frame))
43+
44+
def test_frame_fback_api(self):
45+
"""Test that accessing `f_back` does not cause a segmentation fault on
46+
a frame created with `PyFrame_New` (GH-99110)."""
47+
def dummy():
48+
pass
49+
50+
frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
51+
# The following line should not cause a segmentation fault.
52+
self.assertIsNone(frame.f_back)
53+
54+
55+
if __name__ == "__main__":
56+
unittest.main()

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

Lib/test/test_frame.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
import threading
77
import unittest
88
import weakref
9-
try:
10-
import _testcapi
11-
except ImportError:
12-
_testcapi = None
139

1410
from collections.abc import Mapping
1511
from test import support
@@ -773,51 +769,6 @@ def f():
773769
self.assertIs(catcher.unraisable.exc_type, TypeError)
774770
self.assertIsNone(weak())
775771

776-
@unittest.skipIf(_testcapi is None, 'need _testcapi')
777-
class TestCAPI(unittest.TestCase):
778-
def getframe(self):
779-
return sys._getframe()
780-
781-
def test_frame_getters(self):
782-
frame = self.getframe()
783-
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
784-
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
785-
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
786-
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))
787-
788-
def test_getvar(self):
789-
current_frame = sys._getframe()
790-
x = 1
791-
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
792-
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
793-
with self.assertRaises(NameError):
794-
_testcapi.frame_getvar(current_frame, "y")
795-
with self.assertRaises(NameError):
796-
_testcapi.frame_getvarstring(current_frame, b"y")
797-
798-
# wrong name type
799-
with self.assertRaises(TypeError):
800-
_testcapi.frame_getvar(current_frame, b'x')
801-
with self.assertRaises(TypeError):
802-
_testcapi.frame_getvar(current_frame, 123)
803-
804-
def getgenframe(self):
805-
yield sys._getframe()
806-
807-
def test_frame_get_generator(self):
808-
gen = self.getgenframe()
809-
frame = next(gen)
810-
self.assertIs(gen, _testcapi.frame_getgenerator(frame))
811-
812-
def test_frame_fback_api(self):
813-
"""Test that accessing `f_back` does not cause a segmentation fault on
814-
a frame created with `PyFrame_New` (GH-99110)."""
815-
def dummy():
816-
pass
817-
818-
frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
819-
# The following line should not cause a segmentation fault.
820-
self.assertIsNone(frame.f_back)
821772

822773
if __name__ == "__main__":
823774
unittest.main()

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 _testcapi/import.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/import.c _testcapi/frame.c _testcapi/function.c _testcapi/type.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 _testlimitedcapi/file.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},

0 commit comments

Comments
 (0)
0