Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
160 changes: 160 additions & 0 deletions Lib/test/test_capi/test_bytearray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import unittest
import sys
from test.support import import_helper

_testcapi = import_helper.import_module('_testcapi')

NULL = None

class ByteArraySubclass(bytearray):
pass

class BytesLike:
def __init__(self, value):
self.value = value
def __bytes__(self):
return self.value


class CAPITest(unittest.TestCase):
def test_check(self):
# Test PyByteArray_Check()
check = _testcapi.bytearray_check
self.assertTrue(check(bytearray(b'abc')))
self.assertFalse(check(b'abc'))
self.assertTrue(check(ByteArraySubclass(b'abc')))
self.assertFalse(check(BytesLike(b'abc')))
self.assertFalse(check(3))
self.assertFalse(check([]))
self.assertFalse(check(object()))

# CRASHES check(NULL)

def test_checkexact(self):
# Test PyByteArray_CheckExact()
check = _testcapi.bytearray_checkexact
self.assertTrue(check(bytearray(b'abc')))
self.assertFalse(check(b'abc'))
self.assertFalse(check(ByteArraySubclass(b'abc')))
self.assertFalse(check(BytesLike(b'abc')))
self.assertFalse(check(3))
self.assertFalse(check([]))
self.assertFalse(check(object()))

# CRASHES check(NULL)

def test_fromstringandsize(self):
# Test PyByteArray_FromStringAndSize()
fromstringandsize = _testcapi.bytearray_fromstringandsize

self.assertEqual(fromstringandsize(b'abc'), bytearray(b'abc'))
self.assertEqual(fromstringandsize(b'abc', 2), bytearray(b'ab'))
self.assertEqual(fromstringandsize(b'abc\0def'), bytearray(b'abc\0def'))
self.assertEqual(fromstringandsize(b'', 0), bytearray())
self.assertEqual(fromstringandsize(NULL, 0), bytearray())

self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
# TODO: Test PyByteArray_FromStringAndSize(NULL, size) for size != 0

def test_fromobject(self):
# Test PyByteArray_FromObject()
fromobject = _testcapi.bytearray_fromobject

self.assertEqual(fromobject(b'abc'), bytearray(b'abc'))
self.assertEqual(fromobject(bytearray(b'abc')), bytearray(b'abc'))
self.assertEqual(fromobject(ByteArraySubclass(b'abc')), bytearray(b'abc'))
self.assertEqual(fromobject([97, 98, 99]), bytearray(b'abc'))
self.assertEqual(fromobject(3), bytearray(b'\0\0\0'))
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
self.assertRaises(TypeError, fromobject, 'abc')
self.assertRaises(TypeError, fromobject, object())

# CRASHES fromobject(NULL)

def test_size(self):
# Test PyByteArray_Size()
size = _testcapi.bytearray_size

self.assertEqual(size(bytearray(b'abc')), 3)
self.assertEqual(size(ByteArraySubclass(b'abc')), 3)

# CRASHES size(b'abc')
# CRASHES size(object())
# CRASHES size(NULL)

def test_asstring(self):
"""Test PyUnicode_AsString()"""
asstring = _testcapi.bytearray_asstring

self.assertEqual(asstring(bytearray(b'abc'), 4), b'abc\0')
self.assertEqual(asstring(ByteArraySubclass(b'abc'), 4), b'abc\0')
self.assertEqual(asstring(bytearray(b'abc\0def'), 8), b'abc\0def\0')

# CRASHES asstring(b'abc', 0)
# CRASHES asstring(object()', 0)
# CRASHES asstring(NULL, 0)

def test_concat(self):
"""Test PyByteArray_Concat()"""
concat = _testcapi.bytearray_concat

ba = bytearray(b'abc')
self.assertEqual(concat(ba, b'def'), bytearray(b'abcdef'))
self.assertEqual(ba, b'abc')

self.assertEqual(concat(b'abc', b'def'), bytearray(b'abcdef'))
self.assertEqual(concat(b'a\0b', b'c\0d'), bytearray(b'a\0bc\0d'))
self.assertEqual(concat(bytearray(b'abc'), b'def'), bytearray(b'abcdef'))
self.assertEqual(concat(b'abc', bytearray(b'def')), bytearray(b'abcdef'))
self.assertEqual(concat(bytearray(b'abc'), b''), bytearray(b'abc'))
self.assertEqual(concat(b'', bytearray(b'def')), bytearray(b'def'))
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'),
bytearray(b'abcdef'))
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]),
bytearray(b'abcdef'))

self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
self.assertRaises(TypeError, concat, b'abc', 'def')
self.assertRaises(TypeError, concat, 'abc', b'def')
self.assertRaises(TypeError, concat, 'abc', 'def')
self.assertRaises(TypeError, concat, [], b'def')
self.assertRaises(TypeError, concat, b'abc', [])
self.assertRaises(TypeError, concat, [], [])

# CRASHES concat(NULL, bytearray(b'def'))
# CRASHES concat(bytearray(b'abc'), NULL)
# CRASHES concat(NULL, object())
# CRASHES concat(object(), NULL)

def test_resize(self):
"""Test PyByteArray_Resize()"""
resize = _testcapi.bytearray_resize

ba = bytearray(b'abcdef')
self.assertEqual(resize(ba, 3), 0)
self.assertEqual(ba, bytearray(b'abc'))
self.assertEqual(resize(ba, 10), 0)
self.assertEqual(len(ba), 10)
self.assertEqual(ba[:3], bytearray(b'abc'))
self.assertEqual(resize(ba, 2**20), 0)
self.assertEqual(len(ba), 2**20)
self.assertEqual(ba[:3], bytearray(b'abc'))
self.assertEqual(resize(ba, 0), 0)
self.assertEqual(ba, bytearray())

ba = ByteArraySubclass(b'abcdef')
self.assertEqual(resize(ba, 3), 0)
self.assertEqual(ba, bytearray(b'abc'))

self.assertRaises(MemoryError, resize, bytearray(), sys.maxsize)
self.assertRaises(MemoryError, resize, bytearray(1000), sys.maxsize)

# CRASHES resize(bytearray(b'abc'), -1)
# CRASHES resize(b'abc', 0)
# CRASHES resize(object(), 0)
# CRASHES resize(NULL, 0)


if __name__ == "__main__":
unittest.main()
213 changes: 213 additions & 0 deletions Lib/test/test_capi/test_bytes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import unittest
from test.support import import_helper

_testcapi = import_helper.import_module('_testcapi')

NULL = None

class BytesSubclass(bytes):
pass

class BytesLike:
def __init__(self, value):
self.value = value
def __bytes__(self):
return self.value


class CAPITest(unittest.TestCase):
def test_check(self):
# Test PyBytes_Check()
check = _testcapi.bytes_check
self.assertTrue(check(b'abc'))
self.assertFalse(check('abc'))
self.assertFalse(check(bytearray(b'abc')))
self.assertTrue(check(BytesSubclass(b'abc')))
self.assertFalse(check(BytesLike(b'abc')))
self.assertFalse(check(3))
self.assertFalse(check([]))
self.assertFalse(check(object()))

# CRASHES check(NULL)

def test_checkexact(self):
# Test PyBytes_CheckExact()
check = _testcapi.bytes_checkexact
self.assertTrue(check(b'abc'))
self.assertFalse(check('abc'))
self.assertFalse(check(bytearray(b'abc')))
self.assertFalse(check(BytesSubclass(b'abc')))
self.assertFalse(check(BytesLike(b'abc')))
self.assertFalse(check(3))
self.assertFalse(check([]))
self.assertFalse(check(object()))

# CRASHES check(NULL)

def test_fromstringandsize(self):
# Test PyBytes_FromStringAndSize()
fromstringandsize = _testcapi.bytes_fromstringandsize

self.assertEqual(fromstringandsize(b'abc'), b'abc')
self.assertEqual(fromstringandsize(b'abc', 2), b'ab')
self.assertEqual(fromstringandsize(b'abc\0def'), b'abc\0def')
self.assertEqual(fromstringandsize(b'', 0), b'')
self.assertEqual(fromstringandsize(NULL, 0), b'')

self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
# TODO: Test PyBytes_FromStringAndSize(NULL, size) for size != 0

def test_fromstring(self):
# Test PyBytes_FromString()
fromstring = _testcapi.bytes_fromstring

self.assertEqual(fromstring(b'abc\0def'), b'abc')
self.assertEqual(fromstring(b''), b'')

# CRASHES fromstring(NULL)

def test_fromobject(self):
# Test PyBytes_FromObject()
fromobject = _testcapi.bytes_fromobject

self.assertEqual(fromobject(b'abc'), b'abc')
self.assertEqual(fromobject(bytearray(b'abc')), b'abc')
self.assertEqual(fromobject(BytesSubclass(b'abc')), b'abc')
self.assertEqual(fromobject([97, 98, 99]), b'abc')
self.assertRaises(TypeError, fromobject, 3)
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
self.assertRaises(TypeError, fromobject, 'abc')
self.assertRaises(TypeError, fromobject, object())
self.assertRaises(SystemError, fromobject, NULL)

def test_size(self):
# Test PyBytes_Size()
size = _testcapi.bytes_size

self.assertEqual(size(b'abc'), 3)
self.assertEqual(size(BytesSubclass(b'abc')), 3)
self.assertRaises(TypeError, size, bytearray(b'abc'))
self.assertRaises(TypeError, size, 'abc')
self.assertRaises(TypeError, size, object())

# CRASHES size(NULL)

def test_asstring(self):
"""Test PyUnicode_AsString()"""
asstring = _testcapi.bytes_asstring

self.assertEqual(asstring(b'abc', 4), b'abc\0')
self.assertEqual(asstring(b'abc\0def', 8), b'abc\0def\0')
self.assertRaises(TypeError, asstring, 'abc', 0)
self.assertRaises(TypeError, asstring, object(), 0)

# CRASHES asstring(NULL, 0)

def test_asstringandsize(self):
"""Test PyUnicode_AsStringAndSize()"""
asstringandsize = _testcapi.bytes_asstringandsize
asstringandsize_null = _testcapi.bytes_asstringandsize_null

self.assertEqual(asstringandsize(b'abc', 4), (b'abc\0', 3))
self.assertEqual(asstringandsize(b'abc\0def', 8), (b'abc\0def\0', 7))
self.assertEqual(asstringandsize_null(b'abc', 4), b'abc\0')
self.assertRaises(ValueError, asstringandsize_null, b'abc\0def', 8)
self.assertRaises(TypeError, asstringandsize, 'abc', 0)
self.assertRaises(TypeError, asstringandsize_null, 'abc', 0)
self.assertRaises(TypeError, asstringandsize, object(), 0)
self.assertRaises(TypeError, asstringandsize_null, object(), 0)

# CRASHES asstringandsize(NULL, 0)
# CRASHES asstringandsize_null(NULL, 0)

def test_repr(self):
# Test PyBytes_Repr()
bytes_repr = _testcapi.bytes_repr

self.assertEqual(bytes_repr(b'''abc''', 0), r"""b'abc'""")
self.assertEqual(bytes_repr(b'''abc''', 1), r"""b'abc'""")
self.assertEqual(bytes_repr(b'''a'b"c"d''', 0), r"""b'a\'b"c"d'""")
self.assertEqual(bytes_repr(b'''a'b"c"d''', 1), r"""b'a\'b"c"d'""")
self.assertEqual(bytes_repr(b'''a'b"c''', 0), r"""b'a\'b"c'""")
self.assertEqual(bytes_repr(b'''a'b"c''', 1), r"""b'a\'b"c'""")
self.assertEqual(bytes_repr(b'''a'b'c"d''', 0), r"""b'a\'b\'c"d'""")
self.assertEqual(bytes_repr(b'''a'b'c"d''', 1), r"""b'a\'b\'c"d'""")
self.assertEqual(bytes_repr(b'''a'b'c'd''', 0), r"""b'a\'b\'c\'d'""")
self.assertEqual(bytes_repr(b'''a'b'c'd''', 1), r'''b"a'b'c'd"''')

self.assertEqual(bytes_repr(BytesSubclass(b'abc'), 0), r"""b'abc'""")

# UDEFINED bytes_repr(object(), 0)
# CRASHES bytes_repr(NULL, 0)

def test_concat(self, concat=None):
"""Test PyBytes_Concat()"""
if concat is None:
concat = _testcapi.bytes_concat

self.assertEqual(concat(b'abc', b'def'), b'abcdef')
self.assertEqual(concat(b'a\0b', b'c\0d'), b'a\0bc\0d')
self.assertEqual(concat(bytearray(b'abc'), b'def'), b'abcdef')
self.assertEqual(concat(b'abc', bytearray(b'def')), b'abcdef')
self.assertEqual(concat(bytearray(b'abc'), b''), b'abc')
self.assertEqual(concat(b'', bytearray(b'def')), b'def')
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'), b'abcdef')
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]), b'abcdef')

self.assertEqual(concat(b'abc', b'def', True), b'abcdef')
self.assertEqual(concat(b'abc', bytearray(b'def'), True), b'abcdef')
# Check that it does not change the singleton
self.assertEqual(concat(bytes(), b'def', True), b'def')
self.assertEqual(len(bytes()), 0)

self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
self.assertRaises(TypeError, concat, b'abc', 'def')
self.assertRaises(TypeError, concat, 'abc', b'def')
self.assertRaises(TypeError, concat, 'abc', 'def')
self.assertRaises(TypeError, concat, [], b'def')
self.assertRaises(TypeError, concat, b'abc', [])
self.assertRaises(TypeError, concat, [], [])

self.assertEqual(concat(NULL, b'def'), NULL)
self.assertEqual(concat(b'abc', NULL), NULL)
self.assertEqual(concat(NULL, object()), NULL)
self.assertEqual(concat(object(), NULL), NULL)

def test_concatanddel(self):
"""Test PyBytes_ConcatAndDel()"""
self.test_concat(_testcapi.bytes_concatanddel)

def test_decodeescape(self):
"""Test PyBytes_DecodeEscape()"""
decodeescape = _testcapi.bytes_decodeescape

self.assertEqual(decodeescape(b'abc'), b'abc')
self.assertEqual(decodeescape(br'\t\n\r\x0b\x0c\x00\\\'\"'),
b'''\t\n\r\v\f\0\\'"''')
self.assertEqual(decodeescape(b'\t\n\r\x0b\x0c\x00'), b'\t\n\r\v\f\0')
self.assertEqual(decodeescape(br'\xa1\xa2'), b'\xa1\xa2')
self.assertEqual(decodeescape(br'\2\24\241'), b'\x02\x14\xa1')
self.assertEqual(decodeescape(b'\xa1\xa2'), b'\xa1\xa2')
with self.assertWarns(DeprecationWarning):
self.assertEqual(decodeescape(br'\u4f60'), br'\u4f60')
with self.assertWarns(DeprecationWarning):
self.assertEqual(decodeescape(br'\z'), br'\z')
with self.assertWarns(DeprecationWarning):
self.assertEqual(decodeescape(br'\541'), b'a')

for b in b'\\', br'\x', br'\xa', br'\xz', br'\xaz':
self.assertRaises(ValueError, decodeescape, b)
self.assertRaises(ValueError, decodeescape, b, 'strict')
self.assertEqual(decodeescape(br'x\xa', 'replace'), b'x?')
self.assertEqual(decodeescape(br'x\xay', 'replace'), b'x?y')
self.assertEqual(decodeescape(br'x\xa\xy', 'replace'), b'x??y')
self.assertEqual(decodeescape(br'x\xa\xy', 'ignore'), b'xy')
self.assertRaises(ValueError, decodeescape, b'\\', 'spam')
self.assertEqual(decodeescape(NULL), b'')

# CRASHES decodeescape(NULL, NULL, 1)


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 @@ -159,7 +159,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
@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
@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
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

Expand Down
Loading