Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-93649: Split _testcapimodule.c into smaller files #129400

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions Lib/test/test_capi/test_frame.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import sys
import unittest
from test.support import import_helper


_testcapi = import_helper.import_module('_testcapi')


class TestCAPI(unittest.TestCase):
def getframe(self):
return sys._getframe()

def test_frame_getters(self):
frame = self.getframe()
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))

def test_getvar(self):
current_frame = sys._getframe()
x = 1
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
with self.assertRaises(NameError):
_testcapi.frame_getvar(current_frame, "y")
with self.assertRaises(NameError):
_testcapi.frame_getvarstring(current_frame, b"y")

# wrong name type
with self.assertRaises(TypeError):
_testcapi.frame_getvar(current_frame, b'x')
with self.assertRaises(TypeError):
_testcapi.frame_getvar(current_frame, 123)

def getgenframe(self):
yield sys._getframe()

def test_frame_get_generator(self):
gen = self.getgenframe()
frame = next(gen)
self.assertIs(gen, _testcapi.frame_getgenerator(frame))

def test_frame_fback_api(self):
"""Test that accessing `f_back` does not cause a segmentation fault on
a frame created with `PyFrame_New` (GH-99110)."""
def dummy():
pass

frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
# The following line should not cause a segmentation fault.
self.assertIsNone(frame.f_back)


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def check_negative_refcount(self, code):
code = textwrap.dedent(code)
rc, out, err = assert_python_failure('-c', code)
self.assertRegex(err,
br'_testcapimodule\.c:[0-9]+: '
br'object\.c:[0-9]+: '
br'_Py_NegativeRefcount: Assertion failed: '
br'object has negative ref count')

Expand Down
49 changes: 0 additions & 49 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
import threading
import unittest
import weakref
try:
import _testcapi
except ImportError:
_testcapi = None

from collections.abc import Mapping
from test import support
Expand Down Expand Up @@ -773,51 +769,6 @@ def f():
self.assertIs(catcher.unraisable.exc_type, TypeError)
self.assertIsNone(weak())

@unittest.skipIf(_testcapi is None, 'need _testcapi')
class TestCAPI(unittest.TestCase):
def getframe(self):
return sys._getframe()

def test_frame_getters(self):
frame = self.getframe()
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))

def test_getvar(self):
current_frame = sys._getframe()
x = 1
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
with self.assertRaises(NameError):
_testcapi.frame_getvar(current_frame, "y")
with self.assertRaises(NameError):
_testcapi.frame_getvarstring(current_frame, b"y")

# wrong name type
with self.assertRaises(TypeError):
_testcapi.frame_getvar(current_frame, b'x')
with self.assertRaises(TypeError):
_testcapi.frame_getvar(current_frame, 123)

def getgenframe(self):
yield sys._getframe()

def test_frame_get_generator(self):
gen = self.getgenframe()
frame = next(gen)
self.assertIs(gen, _testcapi.frame_getgenerator(frame))

def test_frame_fback_api(self):
"""Test that accessing `f_back` does not cause a segmentation fault on
a frame created with `PyFrame_New` (GH-99110)."""
def dummy():
pass

frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
# The following line should not cause a segmentation fault.
self.assertIsNone(frame.f_back)

if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
@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
@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
@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
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
Expand Down
77 changes: 77 additions & 0 deletions Modules/_testcapi/dict.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,82 @@
#include "parts.h"
#include "util.h"


static int
test_dict_inner(PyObject *self, int count)
{
Py_ssize_t pos = 0, iterations = 0;
int i;
PyObject *dict = PyDict_New();
PyObject *v, *k;

if (dict == NULL)
return -1;

for (i = 0; i < count; i++) {
v = PyLong_FromLong(i);
if (v == NULL) {
goto error;
}
if (PyDict_SetItem(dict, v, v) < 0) {
Py_DECREF(v);
goto error;
}
Py_DECREF(v);
}

k = v = UNINITIALIZED_PTR;
while (PyDict_Next(dict, &pos, &k, &v)) {
PyObject *o;
iterations++;

assert(k != UNINITIALIZED_PTR);
assert(v != UNINITIALIZED_PTR);
i = PyLong_AS_LONG(v) + 1;
o = PyLong_FromLong(i);
if (o == NULL) {
goto error;
}
if (PyDict_SetItem(dict, k, o) < 0) {
Py_DECREF(o);
goto error;
}
Py_DECREF(o);
k = v = UNINITIALIZED_PTR;
}
assert(k == UNINITIALIZED_PTR);
assert(v == UNINITIALIZED_PTR);

Py_DECREF(dict);

if (iterations != count) {
PyErr_SetString(
PyExc_AssertionError,
"test_dict_iteration: dict iteration went wrong ");
return -1;
} else {
return 0;
}
error:
Py_DECREF(dict);
return -1;
}

static PyObject*
test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored))
{
int i;

for (i = 0; i < 200; i++) {
if (test_dict_inner(self, i) < 0) {
return NULL;
}
}

Py_RETURN_NONE;
}


static PyObject *
dict_containsstring(PyObject *self, PyObject *args)
{
Expand Down Expand Up @@ -182,6 +258,7 @@ dict_popstring_null(PyObject *self, PyObject *args)
}

static PyMethodDef test_methods[] = {
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
{"dict_containsstring", dict_containsstring, METH_VARARGS},
{"dict_getitemref", dict_getitemref, METH_VARARGS},
{"dict_getitemstringref", dict_getitemstringref, METH_VARARGS},
Expand Down
58 changes: 58 additions & 0 deletions Modules/_testcapi/float.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,63 @@
#include "clinic/float.c.h"


/* Test PyOS_string_to_double. */
static PyObject *
test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored))
{
double result;
const char *msg;

#define CHECK_STRING(STR, expected) \
do { \
result = PyOS_string_to_double(STR, NULL, NULL); \
if (result == -1.0 && PyErr_Occurred()) { \
return NULL; \
} \
if (result != (double)expected) { \
msg = "conversion of " STR " to float failed"; \
goto fail; \
} \
} while (0)

#define CHECK_INVALID(STR) \
do { \
result = PyOS_string_to_double(STR, NULL, NULL); \
if (result == -1.0 && PyErr_Occurred()) { \
if (PyErr_ExceptionMatches(PyExc_ValueError)) { \
PyErr_Clear(); \
} \
else { \
return NULL; \
} \
} \
else { \
msg = "conversion of " STR " didn't raise ValueError"; \
goto fail; \
} \
} while (0)

CHECK_STRING("0.1", 0.1);
CHECK_STRING("1.234", 1.234);
CHECK_STRING("-1.35", -1.35);
CHECK_STRING(".1e01", 1.0);
CHECK_STRING("2.e-2", 0.02);

CHECK_INVALID(" 0.1");
CHECK_INVALID("\t\n-3");
CHECK_INVALID(".123 ");
CHECK_INVALID("3\n");
CHECK_INVALID("123abc");

Py_RETURN_NONE;
fail:
PyErr_Format(PyExc_AssertionError, "test_string_to_double: %s", msg);
return NULL;
#undef CHECK_STRING
#undef CHECK_INVALID
}


/*[clinic input]
module _testcapi
[clinic start generated code]*/
Expand Down Expand Up @@ -100,6 +157,7 @@ _testcapi_float_unpack_impl(PyObject *module, const char *data,
}

static PyMethodDef test_methods[] = {
{"test_string_to_double", test_string_to_double, METH_NOARGS},
_TESTCAPI_FLOAT_PACK_METHODDEF
_TESTCAPI_FLOAT_UNPACK_METHODDEF
{NULL},
Expand Down
Loading
Loading