Skip to content

Commit 9fbc7e4

Browse files
pythongh-111495: Add tests for PyBytes and PyByteArray C API
1 parent 4a929d4 commit 9fbc7e4

File tree

7 files changed

+395
-1
lines changed

7 files changed

+395
-1
lines changed

Modules/Setup.stdlib.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
160160
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
161161
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c
162-
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c
162+
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c
163163
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
164164
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
165165

Modules/_testcapi/bytearray.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include "parts.h"
2+
#include "util.h"
3+
4+
5+
/* Test PyByteArray_Check() */
6+
static PyObject *
7+
bytearray_check(PyObject *Py_UNUSED(module), PyObject *obj)
8+
{
9+
NULLABLE(obj);
10+
return PyLong_FromLong(PyByteArray_Check(obj));
11+
}
12+
13+
/* Test PyByteArray_CheckExact() */
14+
static PyObject *
15+
bytearray_checkexact(PyObject *Py_UNUSED(module), PyObject *obj)
16+
{
17+
NULLABLE(obj);
18+
return PyLong_FromLong(PyByteArray_CheckExact(obj));
19+
}
20+
21+
/* Test PyByteArray_FromStringAndSize() */
22+
static PyObject *
23+
bytearray_fromstringandsize(PyObject *Py_UNUSED(module), PyObject *args)
24+
{
25+
const char *s;
26+
Py_ssize_t bsize;
27+
Py_ssize_t size = -100;
28+
29+
if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) {
30+
return NULL;
31+
}
32+
33+
if (size == -100) {
34+
size = bsize;
35+
}
36+
return PyByteArray_FromStringAndSize(s, size);
37+
}
38+
39+
/* Test PyByteArray_FromObject() */
40+
static PyObject *
41+
bytearray_fromobject(PyObject *Py_UNUSED(module), PyObject *arg)
42+
{
43+
NULLABLE(arg);
44+
return PyByteArray_FromObject(arg);
45+
}
46+
47+
/* Test PyByteArray_Size() */
48+
static PyObject *
49+
bytearray_size(PyObject *Py_UNUSED(module), PyObject *arg)
50+
{
51+
NULLABLE(arg);
52+
RETURN_SIZE(PyByteArray_Size(arg));
53+
}
54+
55+
/* Test PyUnicode_AsString() */
56+
static PyObject *
57+
bytearray_asstring(PyObject *Py_UNUSED(module), PyObject *args)
58+
{
59+
PyObject *obj;
60+
Py_ssize_t buflen;
61+
const char *s;
62+
63+
if (!PyArg_ParseTuple(args, "On", &obj, &buflen))
64+
return NULL;
65+
66+
NULLABLE(obj);
67+
s = PyByteArray_AsString(obj);
68+
if (s == NULL)
69+
return NULL;
70+
71+
return PyByteArray_FromStringAndSize(s, buflen);
72+
}
73+
74+
/* Test PyByteArray_Concat() */
75+
static PyObject *
76+
bytearray_concat(PyObject *Py_UNUSED(module), PyObject *args)
77+
{
78+
PyObject *left, *right;
79+
80+
if (!PyArg_ParseTuple(args, "OO", &left, &right))
81+
return NULL;
82+
83+
NULLABLE(left);
84+
NULLABLE(right);
85+
return PyByteArray_Concat(left, right);
86+
}
87+
88+
/* Test PyByteArray_Resize() */
89+
static PyObject *
90+
bytearray_resize(PyObject *Py_UNUSED(module), PyObject *args)
91+
{
92+
PyObject *obj;
93+
Py_ssize_t size;
94+
95+
if (!PyArg_ParseTuple(args, "On", &obj, &size))
96+
return NULL;
97+
98+
NULLABLE(obj);
99+
RETURN_INT(PyByteArray_Resize(obj, size));
100+
}
101+
102+
103+
static PyMethodDef test_methods[] = {
104+
{"bytearray_check", bytearray_check, METH_O},
105+
{"bytearray_checkexact", bytearray_checkexact, METH_O},
106+
{"bytearray_fromstringandsize", bytearray_fromstringandsize, METH_VARARGS},
107+
{"bytearray_fromobject", bytearray_fromobject, METH_O},
108+
{"bytearray_size", bytearray_size, METH_O},
109+
{"bytearray_asstring", bytearray_asstring, METH_VARARGS},
110+
{"bytearray_concat", bytearray_concat, METH_VARARGS},
111+
{"bytearray_resize", bytearray_resize, METH_VARARGS},
112+
{NULL},
113+
};
114+
115+
int
116+
_PyTestCapi_Init_ByteArray(PyObject *m)
117+
{
118+
if (PyModule_AddFunctions(m, test_methods) < 0) {
119+
return -1;
120+
}
121+
122+
return 0;
123+
}

Modules/_testcapi/bytes.c

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
#include "parts.h"
2+
#include "util.h"
3+
4+
5+
/* Test PyBytes_Check() */
6+
static PyObject *
7+
bytes_check(PyObject *Py_UNUSED(module), PyObject *obj)
8+
{
9+
NULLABLE(obj);
10+
return PyLong_FromLong(PyBytes_Check(obj));
11+
}
12+
13+
/* Test PyBytes_CheckExact() */
14+
static PyObject *
15+
bytes_checkexact(PyObject *Py_UNUSED(module), PyObject *obj)
16+
{
17+
NULLABLE(obj);
18+
return PyLong_FromLong(PyBytes_CheckExact(obj));
19+
}
20+
21+
/* Test PyBytes_FromStringAndSize() */
22+
static PyObject *
23+
bytes_fromstringandsize(PyObject *Py_UNUSED(module), PyObject *args)
24+
{
25+
const char *s;
26+
Py_ssize_t bsize;
27+
Py_ssize_t size = -100;
28+
29+
if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) {
30+
return NULL;
31+
}
32+
33+
if (size == -100) {
34+
size = bsize;
35+
}
36+
return PyBytes_FromStringAndSize(s, size);
37+
}
38+
39+
/* Test PyBytes_FromString() */
40+
static PyObject *
41+
bytes_fromstring(PyObject *Py_UNUSED(module), PyObject *arg)
42+
{
43+
const char *s;
44+
Py_ssize_t size;
45+
46+
if (!PyArg_Parse(arg, "z#", &s, &size)) {
47+
return NULL;
48+
}
49+
return PyBytes_FromString(s);
50+
}
51+
52+
/* Test PyBytes_FromObject() */
53+
static PyObject *
54+
bytes_fromobject(PyObject *Py_UNUSED(module), PyObject *arg)
55+
{
56+
NULLABLE(arg);
57+
return PyBytes_FromObject(arg);
58+
}
59+
60+
/* Test PyBytes_Size() */
61+
static PyObject *
62+
bytes_size(PyObject *Py_UNUSED(module), PyObject *arg)
63+
{
64+
NULLABLE(arg);
65+
RETURN_SIZE(PyBytes_Size(arg));
66+
}
67+
68+
/* Test PyUnicode_AsString() */
69+
static PyObject *
70+
bytes_asstring(PyObject *Py_UNUSED(module), PyObject *args)
71+
{
72+
PyObject *obj;
73+
Py_ssize_t buflen;
74+
const char *s;
75+
76+
if (!PyArg_ParseTuple(args, "On", &obj, &buflen))
77+
return NULL;
78+
79+
NULLABLE(obj);
80+
s = PyBytes_AsString(obj);
81+
if (s == NULL)
82+
return NULL;
83+
84+
return PyBytes_FromStringAndSize(s, buflen);
85+
}
86+
87+
/* Test PyBytes_AsStringAndSize() */
88+
static PyObject *
89+
bytes_asstringandsize(PyObject *Py_UNUSED(module), PyObject *args)
90+
{
91+
PyObject *obj;
92+
Py_ssize_t buflen;
93+
char *s = UNINITIALIZED_PTR;
94+
Py_ssize_t size = UNINITIALIZED_SIZE;
95+
96+
if (!PyArg_ParseTuple(args, "On", &obj, &buflen))
97+
return NULL;
98+
99+
NULLABLE(obj);
100+
if (PyBytes_AsStringAndSize(obj, &s, &size) < 0) {
101+
return NULL;
102+
}
103+
104+
if (s == NULL) {
105+
return Py_BuildValue("(On)", Py_None, size);
106+
}
107+
else {
108+
return Py_BuildValue("(y#n)", s, buflen, size);
109+
}
110+
}
111+
112+
static PyObject *
113+
bytes_asstringandsize_null(PyObject *Py_UNUSED(module), PyObject *args)
114+
{
115+
PyObject *obj;
116+
Py_ssize_t buflen;
117+
char *s = UNINITIALIZED_PTR;
118+
119+
if (!PyArg_ParseTuple(args, "On", &obj, &buflen))
120+
return NULL;
121+
122+
NULLABLE(obj);
123+
if (PyBytes_AsStringAndSize(obj, &s, NULL) < 0) {
124+
return NULL;
125+
}
126+
127+
if (s == NULL) {
128+
Py_RETURN_NONE;
129+
}
130+
else {
131+
return PyBytes_FromStringAndSize(s, buflen);
132+
}
133+
}
134+
135+
/* Test PyBytes_Repr() */
136+
static PyObject *
137+
bytes_repr(PyObject *Py_UNUSED(module), PyObject *args)
138+
{
139+
PyObject *obj;
140+
int smartquotes;
141+
if (!PyArg_ParseTuple(args, "Oi", &obj, &smartquotes))
142+
return NULL;
143+
144+
NULLABLE(obj);
145+
return PyBytes_Repr(obj, smartquotes);
146+
}
147+
148+
/* Test PyBytes_Concat() */
149+
static PyObject *
150+
bytes_concat(PyObject *Py_UNUSED(module), PyObject *args)
151+
{
152+
PyObject *left, *right;
153+
int new = 0;
154+
155+
if (!PyArg_ParseTuple(args, "OO|p", &left, &right, &new))
156+
return NULL;
157+
158+
NULLABLE(left);
159+
NULLABLE(right);
160+
if (new) {
161+
assert(left != NULL);
162+
assert(PyBytes_CheckExact(left));
163+
left = PyBytes_FromStringAndSize(PyBytes_AS_STRING(left),
164+
PyBytes_GET_SIZE(left));
165+
if (left == NULL) {
166+
return NULL;
167+
}
168+
}
169+
else {
170+
Py_XINCREF(left);
171+
}
172+
PyBytes_Concat(&left, right);
173+
if (left == NULL && !PyErr_Occurred()) {
174+
Py_RETURN_NONE;
175+
}
176+
return left;
177+
}
178+
179+
/* Test PyBytes_ConcatAndDel() */
180+
static PyObject *
181+
bytes_concatanddel(PyObject *Py_UNUSED(module), PyObject *args)
182+
{
183+
PyObject *left, *right;
184+
int new = 0;
185+
186+
if (!PyArg_ParseTuple(args, "OO|p", &left, &right, &new))
187+
return NULL;
188+
189+
NULLABLE(left);
190+
NULLABLE(right);
191+
if (new) {
192+
assert(left != NULL);
193+
assert(PyBytes_CheckExact(left));
194+
left = PyBytes_FromStringAndSize(PyBytes_AS_STRING(left),
195+
PyBytes_GET_SIZE(left));
196+
if (left == NULL) {
197+
return NULL;
198+
}
199+
}
200+
else {
201+
Py_XINCREF(left);
202+
}
203+
Py_XINCREF(right);
204+
PyBytes_ConcatAndDel(&left, right);
205+
if (left == NULL && !PyErr_Occurred()) {
206+
Py_RETURN_NONE;
207+
}
208+
return left;
209+
}
210+
211+
/* Test PyBytes_DecodeEscape() */
212+
static PyObject *
213+
bytes_decodeescape(PyObject *Py_UNUSED(module), PyObject *args)
214+
{
215+
const char *s;
216+
Py_ssize_t bsize;
217+
Py_ssize_t size = -100;
218+
const char *errors = NULL;
219+
220+
if (!PyArg_ParseTuple(args, "z#|zn", &s, &bsize, &errors, &size))
221+
return NULL;
222+
223+
if (size == -100) {
224+
size = bsize;
225+
}
226+
return PyBytes_DecodeEscape(s, size, errors, 0, NULL);
227+
}
228+
229+
230+
static PyMethodDef test_methods[] = {
231+
{"bytes_check", bytes_check, METH_O},
232+
{"bytes_checkexact", bytes_checkexact, METH_O},
233+
{"bytes_fromstringandsize", bytes_fromstringandsize, METH_VARARGS},
234+
{"bytes_fromstring", bytes_fromstring, METH_O},
235+
{"bytes_fromobject", bytes_fromobject, METH_O},
236+
{"bytes_size", bytes_size, METH_O},
237+
{"bytes_asstring", bytes_asstring, METH_VARARGS},
238+
{"bytes_asstringandsize", bytes_asstringandsize, METH_VARARGS},
239+
{"bytes_asstringandsize_null", bytes_asstringandsize_null, METH_VARARGS},
240+
{"bytes_repr", bytes_repr, METH_VARARGS},
241+
{"bytes_concat", bytes_concat, METH_VARARGS},
242+
{"bytes_concatanddel", bytes_concatanddel, METH_VARARGS},
243+
{"bytes_decodeescape", bytes_decodeescape, METH_VARARGS},
244+
{NULL},
245+
};
246+
247+
int
248+
_PyTestCapi_Init_Bytes(PyObject *m)
249+
{
250+
if (PyModule_AddFunctions(m, test_methods) < 0) {
251+
return -1;
252+
}
253+
254+
return 0;
255+
}

Modules/_testcapi/parts.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
int _PyTestCapi_Init_Vectorcall(PyObject *module);
3232
int _PyTestCapi_Init_Heaptype(PyObject *module);
3333
int _PyTestCapi_Init_Abstract(PyObject *module);
34+
int _PyTestCapi_Init_ByteArray(PyObject *);
35+
int _PyTestCapi_Init_Bytes(PyObject *);
3436
int _PyTestCapi_Init_Unicode(PyObject *module);
3537
int _PyTestCapi_Init_GetArgs(PyObject *module);
3638
int _PyTestCapi_Init_DateTime(PyObject *module);

0 commit comments

Comments
 (0)