summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_capi
diff options
context:
space:
mode:
authorSergey B Kirpichev <skirpichev@gmail.com>2024-08-26 09:57:52 (GMT)
committerGitHub <noreply@github.com>2024-08-26 09:57:52 (GMT)
commitdbc1752d4107532d312c78263212e807a3674eb1 (patch)
treee3c905aaa34e557db023300e4fe8a640bf3532a0 /Lib/test/test_capi
parent6401cdf90810252a0de1775cac2f4f2f7c6b1d5a (diff)
downloadcpython-dbc1752d4107532d312c78263212e807a3674eb1.zip
cpython-dbc1752d4107532d312c78263212e807a3674eb1.tar.gz
cpython-dbc1752d4107532d312c78263212e807a3674eb1.tar.bz2
gh-111495: Add tests for PyTuple C API (#118757)
Co-authored-by: kalyanr <kalyan.ben10@live.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/test/test_capi')
-rw-r--r--Lib/test/test_capi/test_hash.py4
-rw-r--r--Lib/test/test_capi/test_list.py4
-rw-r--r--Lib/test/test_capi/test_set.py4
-rw-r--r--Lib/test/test_capi/test_time.py4
-rw-r--r--Lib/test/test_capi/test_tuple.py261
5 files changed, 277 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_hash.py b/Lib/test/test_capi/test_hash.py
index 8436da7..cb2b363 100644
--- a/Lib/test/test_capi/test_hash.py
+++ b/Lib/test/test_capi/test_hash.py
@@ -77,3 +77,7 @@ class CAPITest(unittest.TestCase):
# Py_HashPointer((void*)(uintptr_t)-1) doesn't return -1 but -2
VOID_P_MAX = -1 & (2 ** (8 * SIZEOF_VOID_P) - 1)
self.assertEqual(hash_pointer(VOID_P_MAX), -2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_capi/test_list.py b/Lib/test/test_capi/test_list.py
index 83e4120..fb3cb3c 100644
--- a/Lib/test/test_capi/test_list.py
+++ b/Lib/test/test_capi/test_list.py
@@ -345,3 +345,7 @@ class CAPITest(unittest.TestCase):
# CRASHES list_extend(NULL, [])
# CRASHES list_extend([], NULL)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_capi/test_set.py b/Lib/test/test_capi/test_set.py
index 499a514..62d90a3 100644
--- a/Lib/test/test_capi/test_set.py
+++ b/Lib/test/test_capi/test_set.py
@@ -265,3 +265,7 @@ class TestInternalCAPI(BaseSetTests, unittest.TestCase):
with self.assertRaises(SystemError):
set_next(object(), 0)
# CRASHES: set_next(NULL, 0)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_capi/test_time.py b/Lib/test/test_capi/test_time.py
index 17ebd7c..989c158 100644
--- a/Lib/test/test_capi/test_time.py
+++ b/Lib/test/test_capi/test_time.py
@@ -72,3 +72,7 @@ class CAPITest(unittest.TestCase):
# Test PyTime_Time() and PyTime_TimeRaw()
self.check_clock(_testcapi.PyTime_Time, time.time)
self.check_clock(_testcapi.PyTime_TimeRaw, time.time)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_capi/test_tuple.py b/Lib/test/test_capi/test_tuple.py
new file mode 100644
index 0000000..e6b49ca
--- /dev/null
+++ b/Lib/test/test_capi/test_tuple.py
@@ -0,0 +1,261 @@
+import unittest
+import sys
+from collections import namedtuple
+from test.support import import_helper
+
+_testcapi = import_helper.import_module('_testcapi')
+_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
+
+NULL = None
+PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN
+PY_SSIZE_T_MAX = _testcapi.PY_SSIZE_T_MAX
+
+class TupleSubclass(tuple):
+ pass
+
+
+class CAPITest(unittest.TestCase):
+ def test_check(self):
+ # Test PyTuple_Check()
+ check = _testlimitedcapi.tuple_check
+
+ self.assertTrue(check((1, 2)))
+ self.assertTrue(check(()))
+ self.assertTrue(check(TupleSubclass((1, 2))))
+ self.assertFalse(check({1: 2}))
+ self.assertFalse(check([1, 2]))
+ self.assertFalse(check(42))
+ self.assertFalse(check(object()))
+
+ # CRASHES check(NULL)
+
+ def test_tuple_checkexact(self):
+ # Test PyTuple_CheckExact()
+ check = _testlimitedcapi.tuple_checkexact
+
+ self.assertTrue(check((1, 2)))
+ self.assertTrue(check(()))
+ self.assertFalse(check(TupleSubclass((1, 2))))
+ self.assertFalse(check({1: 2}))
+ self.assertFalse(check([1, 2]))
+ self.assertFalse(check(42))
+ self.assertFalse(check(object()))
+
+ # CRASHES check(NULL)
+
+ def test_tuple_new(self):
+ # Test PyTuple_New()
+ tuple_new = _testlimitedcapi.tuple_new
+ size = _testlimitedcapi.tuple_size
+ checknull = _testcapi._check_tuple_item_is_NULL
+
+ tup1 = tuple_new(0)
+ self.assertEqual(tup1, ())
+ self.assertEqual(size(tup1), 0)
+ self.assertIs(type(tup1), tuple)
+ tup2 = tuple_new(1)
+ self.assertIs(type(tup2), tuple)
+ self.assertEqual(size(tup2), 1)
+ self.assertIsNot(tup2, tup1)
+ self.assertTrue(checknull(tup2, 0))
+
+ self.assertRaises(SystemError, tuple_new, -1)
+ self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
+ self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
+
+ def test_tuple_pack(self):
+ # Test PyTuple_Pack()
+ pack = _testlimitedcapi.tuple_pack
+
+ self.assertEqual(pack(0), ())
+ self.assertEqual(pack(1, [1]), ([1],))
+ self.assertEqual(pack(2, [1], [2]), ([1], [2]))
+
+ self.assertRaises(SystemError, pack, PY_SSIZE_T_MIN)
+ self.assertRaises(SystemError, pack, -1)
+ self.assertRaises(MemoryError, pack, PY_SSIZE_T_MAX)
+
+ # CRASHES pack(1, NULL)
+ # CRASHES pack(2, [1])
+
+ def test_tuple_size(self):
+ # Test PyTuple_Size()
+ size = _testlimitedcapi.tuple_size
+
+ self.assertEqual(size(()), 0)
+ self.assertEqual(size((1, 2)), 2)
+ self.assertEqual(size(TupleSubclass((1, 2))), 2)
+
+ self.assertRaises(SystemError, size, [])
+ self.assertRaises(SystemError, size, 42)
+ self.assertRaises(SystemError, size, object())
+
+ # CRASHES size(NULL)
+
+ def test_tuple_get_size(self):
+ # Test PyTuple_GET_SIZE()
+ size = _testcapi.tuple_get_size
+
+ self.assertEqual(size(()), 0)
+ self.assertEqual(size((1, 2)), 2)
+ self.assertEqual(size(TupleSubclass((1, 2))), 2)
+
+ def test_tuple_getitem(self):
+ # Test PyTuple_GetItem()
+ getitem = _testlimitedcapi.tuple_getitem
+
+ tup = ([1], [2], [3])
+ self.assertEqual(getitem(tup, 0), [1])
+ self.assertEqual(getitem(tup, 2), [3])
+
+ tup2 = TupleSubclass(([1], [2], [3]))
+ self.assertEqual(getitem(tup2, 0), [1])
+ self.assertEqual(getitem(tup2, 2), [3])
+
+ self.assertRaises(IndexError, getitem, tup, PY_SSIZE_T_MIN)
+ self.assertRaises(IndexError, getitem, tup, -1)
+ self.assertRaises(IndexError, getitem, tup, len(tup))
+ self.assertRaises(IndexError, getitem, tup, PY_SSIZE_T_MAX)
+ self.assertRaises(SystemError, getitem, [1, 2, 3], 1)
+ self.assertRaises(SystemError, getitem, 42, 1)
+
+ # CRASHES getitem(NULL, 0)
+
+ def test_tuple_get_item(self):
+ # Test PyTuple_GET_ITEM()
+ get_item = _testcapi.tuple_get_item
+
+ tup = ([1], [2], [3])
+ self.assertEqual(get_item(tup, 0), [1])
+ self.assertEqual(get_item(tup, 2), [3])
+
+ tup2 = TupleSubclass(([1], [2], [3]))
+ self.assertEqual(get_item(tup2, 0), [1])
+ self.assertEqual(get_item(tup2, 2), [3])
+
+ # CRASHES get_item(NULL, 0)
+
+ def test_tuple_getslice(self):
+ # Test PyTuple_GetSlice()
+ getslice = _testlimitedcapi.tuple_getslice
+
+ # empty
+ tup = ([1], [2], [3])
+ self.assertEqual(getslice(tup, PY_SSIZE_T_MIN, 0), ())
+ self.assertEqual(getslice(tup, -1, 0), ())
+ self.assertEqual(getslice(tup, 3, PY_SSIZE_T_MAX), ())
+ self.assertEqual(getslice(tup, 1, 1), ())
+ self.assertEqual(getslice(tup, 2, 1), ())
+ tup = TupleSubclass(([1], [2], [3]))
+ self.assertEqual(getslice(tup, PY_SSIZE_T_MIN, 0), ())
+ self.assertEqual(getslice(tup, -1, 0), ())
+ self.assertEqual(getslice(tup, 3, PY_SSIZE_T_MAX), ())
+ self.assertEqual(getslice(tup, 1, 1), ())
+ self.assertEqual(getslice(tup, 2, 1), ())
+
+ # slice
+ tup = ([1], [2], [3], [4])
+ self.assertEqual(getslice(tup, 1, 3), ([2], [3]))
+ tup = TupleSubclass(([1], [2], [3], [4]))
+ self.assertEqual(getslice(tup, 1, 3), ([2], [3]))
+
+ # whole
+ tup = ([1], [2], [3])
+ self.assertEqual(getslice(tup, 0, 3), tup)
+ self.assertEqual(getslice(tup, 0, 100), tup)
+ self.assertEqual(getslice(tup, -100, 100), tup)
+ tup = TupleSubclass(([1], [2], [3]))
+ self.assertEqual(getslice(tup, 0, 3), tup)
+ self.assertEqual(getslice(tup, 0, 100), tup)
+ self.assertEqual(getslice(tup, -100, 100), tup)
+
+ self.assertRaises(SystemError, getslice, [[1], [2], [3]], 0, 0)
+ self.assertRaises(SystemError, getslice, 42, 0, 0)
+
+ # CRASHES getslice(NULL, 0, 0)
+
+ def test_tuple_setitem(self):
+ # Test PyTuple_SetItem()
+ setitem = _testlimitedcapi.tuple_setitem
+ checknull = _testcapi._check_tuple_item_is_NULL
+
+ tup = ([1], [2])
+ self.assertEqual(setitem(tup, 0, []), ([], [2]))
+ self.assertEqual(setitem(tup, 1, []), ([1], []))
+
+ tup2 = setitem(tup, 1, NULL)
+ self.assertTrue(checknull(tup2, 1))
+
+ tup2 = TupleSubclass(([1], [2]))
+ self.assertRaises(SystemError, setitem, tup2, 0, [])
+
+ self.assertRaises(IndexError, setitem, tup, PY_SSIZE_T_MIN, [])
+ self.assertRaises(IndexError, setitem, tup, -1, [])
+ self.assertRaises(IndexError, setitem, tup, len(tup), [])
+ self.assertRaises(IndexError, setitem, tup, PY_SSIZE_T_MAX, [])
+ self.assertRaises(SystemError, setitem, [1], 0, [])
+ self.assertRaises(SystemError, setitem, 42, 0, [])
+
+ # CRASHES setitem(NULL, 0, [])
+
+ def test_tuple_set_item(self):
+ # Test PyTuple_SET_ITEM()
+ set_item = _testcapi.tuple_set_item
+ checknull = _testcapi._check_tuple_item_is_NULL
+
+ tup = ([1], [2])
+ self.assertEqual(set_item(tup, 0, []), ([], [2]))
+ self.assertEqual(set_item(tup, 1, []), ([1], []))
+
+ tup2 = set_item(tup, 1, NULL)
+ self.assertTrue(checknull(tup2, 1))
+
+ tup2 = TupleSubclass(([1], [2]))
+ self.assertIs(set_item(tup2, 0, []), tup2)
+ self.assertEqual(tup2, ([], [2]))
+
+ # CRASHES set_item(tup, -1, [])
+ # CRASHES set_item(tup, len(tup), [])
+ # CRASHES set_item([1], 0, [])
+ # CRASHES set_item(NULL, 0, [])
+
+ def test__tuple_resize(self):
+ # Test _PyTuple_Resize()
+ resize = _testcapi._tuple_resize
+ checknull = _testcapi._check_tuple_item_is_NULL
+
+ a = ()
+ b = resize(a, 0, False)
+ self.assertEqual(len(a), 0)
+ self.assertEqual(len(b), 0)
+ b = resize(a, 2, False)
+ self.assertEqual(len(a), 0)
+ self.assertEqual(len(b), 2)
+ self.assertTrue(checknull(b, 0))
+ self.assertTrue(checknull(b, 1))
+
+ a = ([1], [2], [3])
+ b = resize(a, 3)
+ self.assertEqual(b, a)
+ b = resize(a, 2)
+ self.assertEqual(b, a[:2])
+ b = resize(a, 5)
+ self.assertEqual(len(b), 5)
+ self.assertEqual(b[:3], a)
+ self.assertTrue(checknull(b, 3))
+ self.assertTrue(checknull(b, 4))
+
+ a = ()
+ self.assertRaises(MemoryError, resize, a, PY_SSIZE_T_MAX)
+ self.assertRaises(SystemError, resize, a, -1)
+ self.assertRaises(SystemError, resize, a, PY_SSIZE_T_MIN)
+ # refcount > 1
+ a = (1, 2, 3)
+ self.assertRaises(SystemError, resize, a, 3, False)
+ self.assertRaises(SystemError, resize, a, 0, False)
+ # non-tuple
+ self.assertRaises(SystemError, resize, [1, 2, 3], 0, False)
+ self.assertRaises(SystemError, resize, NULL, 0, False)
+
+if __name__ == "__main__":
+ unittest.main()