Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-111495: Add tests for PyTuple C API#118757
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
0e590c4ddf0af7571da3169d9ead3260ef4b5b46641d53b0f32481448451a4db2d0eaca977efa95d154414b3594f9554bce79616f26fc5a25047d6da2ea4c472aa1edf10160c8a6d636266de84190e88ad25eae8File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) | ||
skirpichev marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| # 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 | ||
skirpichev marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 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) | ||
skirpichev marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 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) | ||
serhiy-storchaka marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 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) | ||
skirpichev marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| self.assertEqual(b, a[:2]) | ||
| b = resize(a, 5) | ||
| self.assertEqual(len(b), 5) | ||
| self.assertEqual(b[:3], a) | ||
skirpichev marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 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 | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't get how you make sure that the refcount is > 1 ? Maybe add self.assertGreater(sys.getrefcount(a), 1)? Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One reference from the local variable and other from a function argument. Actually, it is > 1 in all other tests too. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok, it makes sense. | ||
| 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() | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.