Skip to content

Commit f347c3b

Browse files
serhiy-storchakamiss-islington
authored andcommitted
gh-111495: Add tests for PyBytes and PyByteArray C API (GH-111496)
(cherry picked from commit 97b3cd3) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent e255794 commit f347c3b

File tree

5 files changed

+725
-1
lines changed

5 files changed

+725
-1
lines changed

Lib/test/test_capi/test_bytearray.py

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import unittest
2+
import sys
3+
from test.support import import_helper
4+
5+
_testcapi = import_helper.import_module('_testcapi')
6+
7+
NULL = None
8+
9+
class ByteArraySubclass(bytearray):
10+
pass
11+
12+
class BytesLike:
13+
def __init__(self, value):
14+
self.value = value
15+
def __bytes__(self):
16+
return self.value
17+
18+
19+
class CAPITest(unittest.TestCase):
20+
def test_check(self):
21+
# Test PyByteArray_Check()
22+
check = _testcapi.bytearray_check
23+
self.assertTrue(check(bytearray(b'abc')))
24+
self.assertFalse(check(b'abc'))
25+
self.assertTrue(check(ByteArraySubclass(b'abc')))
26+
self.assertFalse(check(BytesLike(b'abc')))
27+
self.assertFalse(check(3))
28+
self.assertFalse(check([]))
29+
self.assertFalse(check(object()))
30+
31+
# CRASHES check(NULL)
32+
33+
def test_checkexact(self):
34+
# Test PyByteArray_CheckExact()
35+
check = _testcapi.bytearray_checkexact
36+
self.assertTrue(check(bytearray(b'abc')))
37+
self.assertFalse(check(b'abc'))
38+
self.assertFalse(check(ByteArraySubclass(b'abc')))
39+
self.assertFalse(check(BytesLike(b'abc')))
40+
self.assertFalse(check(3))
41+
self.assertFalse(check([]))
42+
self.assertFalse(check(object()))
43+
44+
# CRASHES check(NULL)
45+
46+
def test_fromstringandsize(self):
47+
# Test PyByteArray_FromStringAndSize()
48+
fromstringandsize = _testcapi.bytearray_fromstringandsize
49+
50+
self.assertEqual(fromstringandsize(b'abc'), bytearray(b'abc'))
51+
self.assertEqual(fromstringandsize(b'abc', 2), bytearray(b'ab'))
52+
self.assertEqual(fromstringandsize(b'abc\0def'), bytearray(b'abc\0def'))
53+
self.assertEqual(fromstringandsize(b'', 0), bytearray())
54+
self.assertEqual(fromstringandsize(NULL, 0), bytearray())
55+
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
56+
self.assertRaises(MemoryError, fromstringandsize, NULL, sys.maxsize)
57+
58+
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
59+
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
60+
61+
def test_fromobject(self):
62+
# Test PyByteArray_FromObject()
63+
fromobject = _testcapi.bytearray_fromobject
64+
65+
self.assertEqual(fromobject(b'abc'), bytearray(b'abc'))
66+
self.assertEqual(fromobject(bytearray(b'abc')), bytearray(b'abc'))
67+
self.assertEqual(fromobject(ByteArraySubclass(b'abc')), bytearray(b'abc'))
68+
self.assertEqual(fromobject([97, 98, 99]), bytearray(b'abc'))
69+
self.assertEqual(fromobject(3), bytearray(b'\0\0\0'))
70+
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
71+
self.assertRaises(TypeError, fromobject, 'abc')
72+
self.assertRaises(TypeError, fromobject, object())
73+
74+
# CRASHES fromobject(NULL)
75+
76+
def test_size(self):
77+
# Test PyByteArray_Size()
78+
size = _testcapi.bytearray_size
79+
80+
self.assertEqual(size(bytearray(b'abc')), 3)
81+
self.assertEqual(size(ByteArraySubclass(b'abc')), 3)
82+
83+
# CRASHES size(b'abc')
84+
# CRASHES size(object())
85+
# CRASHES size(NULL)
86+
87+
def test_asstring(self):
88+
"""Test PyByteArray_AsString()"""
89+
asstring = _testcapi.bytearray_asstring
90+
91+
self.assertEqual(asstring(bytearray(b'abc'), 4), b'abc\0')
92+
self.assertEqual(asstring(ByteArraySubclass(b'abc'), 4), b'abc\0')
93+
self.assertEqual(asstring(bytearray(b'abc\0def'), 8), b'abc\0def\0')
94+
95+
# CRASHES asstring(b'abc', 0)
96+
# CRASHES asstring(object()', 0)
97+
# CRASHES asstring(NULL, 0)
98+
99+
def test_concat(self):
100+
"""Test PyByteArray_Concat()"""
101+
concat = _testcapi.bytearray_concat
102+
103+
ba = bytearray(b'abc')
104+
self.assertEqual(concat(ba, b'def'), bytearray(b'abcdef'))
105+
self.assertEqual(ba, b'abc')
106+
107+
self.assertEqual(concat(b'abc', b'def'), bytearray(b'abcdef'))
108+
self.assertEqual(concat(b'a\0b', b'c\0d'), bytearray(b'a\0bc\0d'))
109+
self.assertEqual(concat(bytearray(b'abc'), b'def'), bytearray(b'abcdef'))
110+
self.assertEqual(concat(b'abc', bytearray(b'def')), bytearray(b'abcdef'))
111+
self.assertEqual(concat(bytearray(b'abc'), b''), bytearray(b'abc'))
112+
self.assertEqual(concat(b'', bytearray(b'def')), bytearray(b'def'))
113+
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'),
114+
bytearray(b'abcdef'))
115+
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]),
116+
bytearray(b'abcdef'))
117+
118+
self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
119+
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
120+
self.assertRaises(TypeError, concat, b'abc', 'def')
121+
self.assertRaises(TypeError, concat, 'abc', b'def')
122+
self.assertRaises(TypeError, concat, 'abc', 'def')
123+
self.assertRaises(TypeError, concat, [], b'def')
124+
self.assertRaises(TypeError, concat, b'abc', [])
125+
self.assertRaises(TypeError, concat, [], [])
126+
127+
# CRASHES concat(NULL, bytearray(b'def'))
128+
# CRASHES concat(bytearray(b'abc'), NULL)
129+
# CRASHES concat(NULL, object())
130+
# CRASHES concat(object(), NULL)
131+
132+
def test_resize(self):
133+
"""Test PyByteArray_Resize()"""
134+
resize = _testcapi.bytearray_resize
135+
136+
ba = bytearray(b'abcdef')
137+
self.assertEqual(resize(ba, 3), 0)
138+
self.assertEqual(ba, bytearray(b'abc'))
139+
self.assertEqual(resize(ba, 10), 0)
140+
self.assertEqual(len(ba), 10)
141+
self.assertEqual(ba[:3], bytearray(b'abc'))
142+
self.assertEqual(resize(ba, 2**20), 0)
143+
self.assertEqual(len(ba), 2**20)
144+
self.assertEqual(ba[:3], bytearray(b'abc'))
145+
self.assertEqual(resize(ba, 0), 0)
146+
self.assertEqual(ba, bytearray())
147+
148+
ba = ByteArraySubclass(b'abcdef')
149+
self.assertEqual(resize(ba, 3), 0)
150+
self.assertEqual(ba, bytearray(b'abc'))
151+
152+
self.assertRaises(MemoryError, resize, bytearray(), sys.maxsize)
153+
self.assertRaises(MemoryError, resize, bytearray(1000), sys.maxsize)
154+
155+
# CRASHES resize(bytearray(b'abc'), -1)
156+
# CRASHES resize(b'abc', 0)
157+
# CRASHES resize(object(), 0)
158+
# CRASHES resize(NULL, 0)
159+
160+
161+
if __name__ == "__main__":
162+
unittest.main()

Lib/test/test_capi/test_bytes.py

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import unittest
2+
import sys
3+
from test.support import import_helper
4+
5+
_testcapi = import_helper.import_module('_testcapi')
6+
7+
NULL = None
8+
9+
class BytesSubclass(bytes):
10+
pass
11+
12+
class BytesLike:
13+
def __init__(self, value):
14+
self.value = value
15+
def __bytes__(self):
16+
return self.value
17+
18+
19+
class CAPITest(unittest.TestCase):
20+
def test_check(self):
21+
# Test PyBytes_Check()
22+
check = _testcapi.bytes_check
23+
self.assertTrue(check(b'abc'))
24+
self.assertFalse(check('abc'))
25+
self.assertFalse(check(bytearray(b'abc')))
26+
self.assertTrue(check(BytesSubclass(b'abc')))
27+
self.assertFalse(check(BytesLike(b'abc')))
28+
self.assertFalse(check(3))
29+
self.assertFalse(check([]))
30+
self.assertFalse(check(object()))
31+
32+
# CRASHES check(NULL)
33+
34+
def test_checkexact(self):
35+
# Test PyBytes_CheckExact()
36+
check = _testcapi.bytes_checkexact
37+
self.assertTrue(check(b'abc'))
38+
self.assertFalse(check('abc'))
39+
self.assertFalse(check(bytearray(b'abc')))
40+
self.assertFalse(check(BytesSubclass(b'abc')))
41+
self.assertFalse(check(BytesLike(b'abc')))
42+
self.assertFalse(check(3))
43+
self.assertFalse(check([]))
44+
self.assertFalse(check(object()))
45+
46+
# CRASHES check(NULL)
47+
48+
def test_fromstringandsize(self):
49+
# Test PyBytes_FromStringAndSize()
50+
fromstringandsize = _testcapi.bytes_fromstringandsize
51+
52+
self.assertEqual(fromstringandsize(b'abc'), b'abc')
53+
self.assertEqual(fromstringandsize(b'abc', 2), b'ab')
54+
self.assertEqual(fromstringandsize(b'abc\0def'), b'abc\0def')
55+
self.assertEqual(fromstringandsize(b'', 0), b'')
56+
self.assertEqual(fromstringandsize(NULL, 0), b'')
57+
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
58+
self.assertRaises((MemoryError, OverflowError), fromstringandsize, NULL, sys.maxsize)
59+
60+
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
61+
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
62+
63+
def test_fromstring(self):
64+
# Test PyBytes_FromString()
65+
fromstring = _testcapi.bytes_fromstring
66+
67+
self.assertEqual(fromstring(b'abc\0def'), b'abc')
68+
self.assertEqual(fromstring(b''), b'')
69+
70+
# CRASHES fromstring(NULL)
71+
72+
def test_fromobject(self):
73+
# Test PyBytes_FromObject()
74+
fromobject = _testcapi.bytes_fromobject
75+
76+
self.assertEqual(fromobject(b'abc'), b'abc')
77+
self.assertEqual(fromobject(bytearray(b'abc')), b'abc')
78+
self.assertEqual(fromobject(BytesSubclass(b'abc')), b'abc')
79+
self.assertEqual(fromobject([97, 98, 99]), b'abc')
80+
self.assertRaises(TypeError, fromobject, 3)
81+
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
82+
self.assertRaises(TypeError, fromobject, 'abc')
83+
self.assertRaises(TypeError, fromobject, object())
84+
self.assertRaises(SystemError, fromobject, NULL)
85+
86+
def test_size(self):
87+
# Test PyBytes_Size()
88+
size = _testcapi.bytes_size
89+
90+
self.assertEqual(size(b'abc'), 3)
91+
self.assertEqual(size(BytesSubclass(b'abc')), 3)
92+
self.assertRaises(TypeError, size, bytearray(b'abc'))
93+
self.assertRaises(TypeError, size, 'abc')
94+
self.assertRaises(TypeError, size, object())
95+
96+
# CRASHES size(NULL)
97+
98+
def test_asstring(self):
99+
"""Test PyBytes_AsString()"""
100+
asstring = _testcapi.bytes_asstring
101+
102+
self.assertEqual(asstring(b'abc', 4), b'abc\0')
103+
self.assertEqual(asstring(b'abc\0def', 8), b'abc\0def\0')
104+
self.assertRaises(TypeError, asstring, 'abc', 0)
105+
self.assertRaises(TypeError, asstring, object(), 0)
106+
107+
# CRASHES asstring(NULL, 0)
108+
109+
def test_asstringandsize(self):
110+
"""Test PyBytes_AsStringAndSize()"""
111+
asstringandsize = _testcapi.bytes_asstringandsize
112+
asstringandsize_null = _testcapi.bytes_asstringandsize_null
113+
114+
self.assertEqual(asstringandsize(b'abc', 4), (b'abc\0', 3))
115+
self.assertEqual(asstringandsize(b'abc\0def', 8), (b'abc\0def\0', 7))
116+
self.assertEqual(asstringandsize_null(b'abc', 4), b'abc\0')
117+
self.assertRaises(ValueError, asstringandsize_null, b'abc\0def', 8)
118+
self.assertRaises(TypeError, asstringandsize, 'abc', 0)
119+
self.assertRaises(TypeError, asstringandsize_null, 'abc', 0)
120+
self.assertRaises(TypeError, asstringandsize, object(), 0)
121+
self.assertRaises(TypeError, asstringandsize_null, object(), 0)
122+
123+
# CRASHES asstringandsize(NULL, 0)
124+
# CRASHES asstringandsize_null(NULL, 0)
125+
126+
def test_repr(self):
127+
# Test PyBytes_Repr()
128+
bytes_repr = _testcapi.bytes_repr
129+
130+
self.assertEqual(bytes_repr(b'''abc''', 0), r"""b'abc'""")
131+
self.assertEqual(bytes_repr(b'''abc''', 1), r"""b'abc'""")
132+
self.assertEqual(bytes_repr(b'''a'b"c"d''', 0), r"""b'a\'b"c"d'""")
133+
self.assertEqual(bytes_repr(b'''a'b"c"d''', 1), r"""b'a\'b"c"d'""")
134+
self.assertEqual(bytes_repr(b'''a'b"c''', 0), r"""b'a\'b"c'""")
135+
self.assertEqual(bytes_repr(b'''a'b"c''', 1), r"""b'a\'b"c'""")
136+
self.assertEqual(bytes_repr(b'''a'b'c"d''', 0), r"""b'a\'b\'c"d'""")
137+
self.assertEqual(bytes_repr(b'''a'b'c"d''', 1), r"""b'a\'b\'c"d'""")
138+
self.assertEqual(bytes_repr(b'''a'b'c'd''', 0), r"""b'a\'b\'c\'d'""")
139+
self.assertEqual(bytes_repr(b'''a'b'c'd''', 1), r'''b"a'b'c'd"''')
140+
141+
self.assertEqual(bytes_repr(BytesSubclass(b'abc'), 0), r"""b'abc'""")
142+
143+
# UDEFINED bytes_repr(object(), 0)
144+
# CRASHES bytes_repr(NULL, 0)
145+
146+
def test_concat(self, concat=None):
147+
"""Test PyBytes_Concat()"""
148+
if concat is None:
149+
concat = _testcapi.bytes_concat
150+
151+
self.assertEqual(concat(b'abc', b'def'), b'abcdef')
152+
self.assertEqual(concat(b'a\0b', b'c\0d'), b'a\0bc\0d')
153+
self.assertEqual(concat(bytearray(b'abc'), b'def'), b'abcdef')
154+
self.assertEqual(concat(b'abc', bytearray(b'def')), b'abcdef')
155+
self.assertEqual(concat(bytearray(b'abc'), b''), b'abc')
156+
self.assertEqual(concat(b'', bytearray(b'def')), b'def')
157+
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'), b'abcdef')
158+
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]), b'abcdef')
159+
160+
self.assertEqual(concat(b'abc', b'def', True), b'abcdef')
161+
self.assertEqual(concat(b'abc', bytearray(b'def'), True), b'abcdef')
162+
# Check that it does not change the singleton
163+
self.assertEqual(concat(bytes(), b'def', True), b'def')
164+
self.assertEqual(len(bytes()), 0)
165+
166+
self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
167+
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
168+
self.assertRaises(TypeError, concat, b'abc', 'def')
169+
self.assertRaises(TypeError, concat, 'abc', b'def')
170+
self.assertRaises(TypeError, concat, 'abc', 'def')
171+
self.assertRaises(TypeError, concat, [], b'def')
172+
self.assertRaises(TypeError, concat, b'abc', [])
173+
self.assertRaises(TypeError, concat, [], [])
174+
175+
self.assertEqual(concat(NULL, b'def'), NULL)
176+
self.assertEqual(concat(b'abc', NULL), NULL)
177+
self.assertEqual(concat(NULL, object()), NULL)
178+
self.assertEqual(concat(object(), NULL), NULL)
179+
180+
def test_concatanddel(self):
181+
"""Test PyBytes_ConcatAndDel()"""
182+
self.test_concat(_testcapi.bytes_concatanddel)
183+
184+
def test_decodeescape(self):
185+
"""Test PyBytes_DecodeEscape()"""
186+
decodeescape = _testcapi.bytes_decodeescape
187+
188+
self.assertEqual(decodeescape(b'abc'), b'abc')
189+
self.assertEqual(decodeescape(br'\t\n\r\x0b\x0c\x00\\\'\"'),
190+
b'''\t\n\r\v\f\0\\'"''')
191+
self.assertEqual(decodeescape(b'\t\n\r\x0b\x0c\x00'), b'\t\n\r\v\f\0')
192+
self.assertEqual(decodeescape(br'\xa1\xa2'), b'\xa1\xa2')
193+
self.assertEqual(decodeescape(br'\2\24\241'), b'\x02\x14\xa1')
194+
self.assertEqual(decodeescape(b'\xa1\xa2'), b'\xa1\xa2')
195+
with self.assertWarns(DeprecationWarning):
196+
self.assertEqual(decodeescape(br'\u4f60'), br'\u4f60')
197+
with self.assertWarns(DeprecationWarning):
198+
self.assertEqual(decodeescape(br'\z'), br'\z')
199+
with self.assertWarns(DeprecationWarning):
200+
self.assertEqual(decodeescape(br'\541'), b'a')
201+
202+
for b in b'\\', br'\x', br'\xa', br'\xz', br'\xaz':
203+
self.assertRaises(ValueError, decodeescape, b)
204+
self.assertRaises(ValueError, decodeescape, b, 'strict')
205+
self.assertEqual(decodeescape(br'x\xa', 'replace'), b'x?')
206+
self.assertEqual(decodeescape(br'x\xay', 'replace'), b'x?y')
207+
self.assertEqual(decodeescape(br'x\xa\xy', 'replace'), b'x??y')
208+
self.assertEqual(decodeescape(br'x\xa\xy', 'ignore'), b'xy')
209+
self.assertRaises(ValueError, decodeescape, b'\\', 'spam')
210+
self.assertEqual(decodeescape(NULL), b'')
211+
212+
# CRASHES decodeescape(NULL, NULL, 1)
213+
214+
215+
if __name__ == "__main__":
216+
unittest.main()

Lib/test/test_capi/test_unicode.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ def test_fromstringandsize(self):
193193
self.assertEqual(fromstringandsize(NULL, 0), '')
194194

195195
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
196-
# TODO: Test PyUnicode_FromStringAndSize(NULL, size) for size != 0
196+
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
197+
self.assertRaises(SystemError, fromstringandsize, NULL, 3)
198+
self.assertRaises(SystemError, fromstringandsize, NULL, sys.maxsize)
197199

198200
@support.cpython_only
199201
@unittest.skipIf(_testcapi is None, 'need _testcapi module')

0 commit comments

Comments
 (0)