From 28ed23f7ca330c69ada2687c5cfdd1befa588240 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:58:50 +0200 Subject: [PATCH] Update `test_array.py` from 3.14.3 --- Lib/test/test_array.py | 369 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 341 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index d9928937e..426454dbb 100644 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -8,16 +8,20 @@ from test import support from test.support import import_helper from test.support import os_helper from test.support import _2G +from test.support import subTests import weakref import pickle import operator import struct import sys +import warnings import array from array import _array_reconstructor as array_reconstructor -sizeof_wchar = array.array('u').itemsize +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + sizeof_wchar = array.array('u').itemsize class ArraySubclass(array.array): @@ -27,7 +31,7 @@ class ArraySubclassWithKwargs(array.array): def __init__(self, typecode, newarg=None): array.array.__init__(self) -typecodes = 'ubBhHiIlLfdqQ' +typecodes = 'uwbBhHiIlLfdqQ' class MiscTest(unittest.TestCase): @@ -93,8 +97,17 @@ UTF16_BE = 19 UTF32_LE = 20 UTF32_BE = 21 + class ArrayReconstructorTest(unittest.TestCase): + def setUp(self): + self.enterContext(warnings.catch_warnings()) + warnings.filterwarnings( + "ignore", + message="The 'u' type code is deprecated and " + "will be removed in Python 3.16", + category=DeprecationWarning) + def test_error(self): self.assertRaises(TypeError, array_reconstructor, "", "b", 0, b"") @@ -176,21 +189,23 @@ class ArrayReconstructorTest(unittest.TestCase): self.assertEqual(a, b, msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' def test_unicode(self): teststr = "Bonne Journ\xe9e \U0002030a\U00020347" testcases = ( (UTF16_LE, "UTF-16-LE"), (UTF16_BE, "UTF-16-BE"), - (UTF32_LE, "UTF-32-LE"), # TODO: RUSTPYTHON - (UTF32_BE, "UTF-32-BE") # TODO: RUSTPYTHON + (UTF32_LE, "UTF-32-LE"), + (UTF32_BE, "UTF-32-BE") ) for testcase in testcases: mformat_code, encoding = testcase - a = array.array('u', teststr) - b = array_reconstructor( - array.array, 'u', mformat_code, teststr.encode(encoding)) - self.assertEqual(a, b, - msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) + for c in 'uw': + a = array.array(c, teststr) + b = array_reconstructor( + array.array, c, mformat_code, teststr.encode(encoding)) + self.assertEqual(a, b, + msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) class BaseTest: @@ -202,6 +217,14 @@ class BaseTest: # outside: An entry that is not in example # minitemsize: the minimum guaranteed itemsize + def setUp(self): + self.enterContext(warnings.catch_warnings()) + warnings.filterwarnings( + "ignore", + message="The 'u' type code is deprecated and " + "will be removed in Python 3.16", + category=DeprecationWarning) + def assertEntryEqual(self, entry1, entry2): self.assertEqual(entry1, entry2) @@ -234,7 +257,7 @@ class BaseTest: self.assertEqual(bi[1], len(a)) def test_byteswap(self): - if self.typecode == 'u': + if self.typecode in ('u', 'w'): example = '\U00100100' else: example = self.example @@ -993,6 +1016,29 @@ class BaseTest: array.array(self.typecode, self.example[3:]+self.example[:-1]) ) + def test_clear(self): + a = array.array(self.typecode, self.example) + with self.assertRaises(TypeError): + a.clear(42) + a.clear() + self.assertEqual(len(a), 0) + self.assertEqual(a.typecode, self.typecode) + + a = array.array(self.typecode) + a.clear() + self.assertEqual(len(a), 0) + self.assertEqual(a.typecode, self.typecode) + + a = array.array(self.typecode, self.example) + a.clear() + a.append(self.example[2]) + a.append(self.example[3]) + self.assertEqual(a, array.array(self.typecode, self.example[2:4])) + + with memoryview(a): + with self.assertRaises(BufferError): + a.clear() + def test_reverse(self): a = array.array(self.typecode, self.example) self.assertRaises(TypeError, a.reverse, 42) @@ -1079,7 +1125,7 @@ class BaseTest: self.assertEqual(m.tobytes(), expected) self.assertRaises(BufferError, a.frombytes, a.tobytes()) self.assertEqual(m.tobytes(), expected) - if self.typecode == 'u': + if self.typecode in ('u', 'w'): self.assertRaises(BufferError, a.fromunicode, a.tounicode()) self.assertEqual(m.tobytes(), expected) self.assertRaises(BufferError, operator.imul, a, 2) @@ -1134,17 +1180,19 @@ class BaseTest: basesize = support.calcvobjsize('Pn2Pi') support.check_sizeof(self, a, basesize) + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' def test_initialize_with_unicode(self): - if self.typecode != 'u': + if self.typecode not in ('u', 'w'): with self.assertRaises(TypeError) as cm: a = array.array(self.typecode, 'foo') self.assertIn("cannot use a str", str(cm.exception)) with self.assertRaises(TypeError) as cm: - a = array.array(self.typecode, array.array('u', 'foo')) + a = array.array(self.typecode, array.array('w', 'foo')) self.assertIn("cannot use a unicode array", str(cm.exception)) else: a = array.array(self.typecode, "foo") a = array.array(self.typecode, array.array('u', 'foo')) + a = array.array(self.typecode, array.array('w', 'foo')) @support.cpython_only def test_obsolete_write_lock(self): @@ -1152,8 +1200,7 @@ class BaseTest: a = array.array('B', b"") self.assertRaises(BufferError, _testcapi.getbuffer_with_null_view, a) - # TODO: RUSTPYTHON - @unittest.expectedFailure + @unittest.expectedFailure # TODO: RUSTPYTHON def test_free_after_iterating(self): support.check_free_after_iterating(self, iter, array.array, (self.typecode,)) @@ -1173,40 +1220,256 @@ class UnicodeTest(StringTest, unittest.TestCase): smallerexample = '\x01\u263a\x00\ufefe' biggerexample = '\x01\u263a\x01\ufeff' outside = str('\x33') - minitemsize = 2 + minitemsize = sizeof_wchar def test_unicode(self): self.assertRaises(TypeError, array.array, 'b', 'foo') - a = array.array('u', '\xa0\xc2\u1234') + a = array.array(self.typecode, '\xa0\xc2\u1234') a.fromunicode(' ') a.fromunicode('') a.fromunicode('') a.fromunicode('\x11abc\xff\u1234') s = a.tounicode() self.assertEqual(s, '\xa0\xc2\u1234 \x11abc\xff\u1234') - self.assertEqual(a.itemsize, sizeof_wchar) + self.assertEqual(a.itemsize, self.minitemsize) s = '\x00="\'a\\b\x80\xff\u0000\u0001\u1234' - a = array.array('u', s) + a = array.array(self.typecode, s) self.assertEqual( repr(a), - "array('u', '\\x00=\"\\'a\\\\b\\x80\xff\\x00\\x01\u1234')") + f"array('{self.typecode}', '\\x00=\"\\'a\\\\b\\x80\xff\\x00\\x01\u1234')") self.assertRaises(TypeError, a.fromunicode) def test_issue17223(self): - # this used to crash - if sizeof_wchar == 4: - # U+FFFFFFFF is an invalid code point in Unicode 6.0 - invalid_str = b'\xff\xff\xff\xff' - else: + if self.typecode == 'u' and sizeof_wchar == 2: # PyUnicode_FromUnicode() cannot fail with 16-bit wchar_t self.skipTest("specific to 32-bit wchar_t") - a = array.array('u', invalid_str) + + # this used to crash + # U+FFFFFFFF is an invalid code point in Unicode 6.0 + invalid_str = b'\xff\xff\xff\xff' + + a = array.array(self.typecode, invalid_str) self.assertRaises(ValueError, a.tounicode) self.assertRaises(ValueError, str, a) + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: DeprecationWarning not triggered + def test_typecode_u_deprecation(self): + with self.assertWarns(DeprecationWarning): + array.array("u") + + def test_empty_string_mem_leak_gh140474(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + for _ in range(1000): + a = array.array('u', '') + self.assertEqual(len(a), 0) + self.assertEqual(a.typecode, 'u') + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_add(self): + return super().test_add() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_extend(self): + return super().test_extend() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_iadd(self): + return super().test_iadd() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_setiadd(self): + return super().test_setiadd() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_setslice(self): + return super().test_setslice() + + +class UCS4Test(UnicodeTest): + typecode = 'w' + minitemsize = 4 + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_buffer(self): + return super().test_buffer() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_buffer_info(self): + return super().test_buffer_info() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_byteswap(self): + return super().test_byteswap() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_clear(self): + return super().test_clear() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_cmp(self): + return super().test_cmp() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_constructor(self): + return super().test_constructor() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_constructor_with_iterable_argument(self): + return super().test_constructor_with_iterable_argument() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_copy(self): + return super().test_copy() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_count(self): + return super().test_count() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_coveritertraverse(self): + return super().test_coveritertraverse() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_deepcopy(self): + return super().test_deepcopy() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_delitem(self): + return super().test_delitem() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_exhausted_iterator(self): + return super().test_exhausted_iterator() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_exhausted_reverse_iterator(self): + return super().test_exhausted_reverse_iterator() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_extended_getslice(self): + return super().test_extended_getslice() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_extended_set_del_slice(self): + return super().test_extended_set_del_slice() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_filewrite(self): + return super().test_filewrite() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_fromarray(self): + return super().test_fromarray() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_fromfile_ioerror(self): + return super().test_fromfile_ioerror() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_getitem(self): + return super().test_getitem() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_getslice(self): + return super().test_getslice() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_imul(self): + return super().test_imul() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_index(self): + return super().test_index() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_insert(self): + return super().test_insert() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_issue17223(self): + return super().test_issue17223() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_iterator_pickle(self): + return super().test_iterator_pickle() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_len(self): + return super().test_len() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_mul(self): + return super().test_mul() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_pickle(self): + return super().test_pickle() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_pickle_for_empty_array(self): + return super().test_pickle_for_empty_array() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_pop(self): + return super().test_pop() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_reduce_ex(self): + return super().test_reduce_ex() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_remove(self): + return super().test_remove() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_repr(self): + return super().test_repr() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_reverse(self): + return super().test_reverse() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_reverse_iterator(self): + return super().test_reverse_iterator() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_reverse_iterator_picking(self): + return super().test_reverse_iterator_picking() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_setitem(self): + return super().test_setitem() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_str(self): + return super().test_str() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_tofrombytes(self): + return super().test_tofrombytes() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_tofromfile(self): + return super().test_tofromfile() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_tofromlist(self): + return super().test_tofromlist() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_unicode(self): + return super().test_unicode() + + @unittest.expectedFailure # TODO: RUSTPYTHON; Add support for 'w' + def test_weakref(self): + return super().test_weakref() + + class NumberTest(BaseTest): def test_extslice(self): @@ -1438,8 +1701,8 @@ class FPTest(NumberTest): if a.itemsize==1: self.assertEqual(a, b) else: - # On alphas treating the byte swapped bit patters as - # floats/doubles results in floating point exceptions + # On alphas treating the byte swapped bit patterns as + # floats/doubles results in floating-point exceptions # => compare the 8bit string values instead self.assertNotEqual(a.tobytes(), b.tobytes()) b.byteswap() @@ -1611,5 +1874,55 @@ class LargeArrayTest(unittest.TestCase): self.assertEqual(ls[:8], list(example[:8])) self.assertEqual(ls[-8:], list(example[-8:])) + def test_gh_128961(self): + a = array.array('i') + it = iter(a) + list(it) + it.__setstate__(0) + self.assertRaises(StopIteration, next, it) + + # Tests for NULL pointer dereference in array.__setitem__ + # when the index conversion mutates the array. + # See: https://github.com/python/cpython/issues/142555. + + @unittest.skip("TODO: RUSTPYTHON; Hangs") + @subTests("dtype", ["b", "B", "h", "H", "i", "l", "q", "I", "L", "Q"]) + def test_setitem_use_after_clear_with_int_data(self, dtype): + victim = array.array(dtype, list(range(64))) + + class Index: + def __index__(self): + victim.clear() + return 0 + + self.assertRaises(IndexError, victim.__setitem__, 1, Index()) + self.assertEqual(len(victim), 0) + + @unittest.skip("TODO: RUSTPYTHON; Hangs") + def test_setitem_use_after_shrink_with_int_data(self): + victim = array.array('b', [1, 2, 3]) + + class Index: + def __index__(self): + victim.pop() + victim.pop() + return 0 + + self.assertRaises(IndexError, victim.__setitem__, 1, Index()) + + @unittest.skip("TODO: RUSTPYTHON; Hangs") + @subTests("dtype", ["f", "d"]) + def test_setitem_use_after_clear_with_float_data(self, dtype): + victim = array.array(dtype, [1.0, 2.0, 3.0]) + + class Float: + def __float__(self): + victim.clear() + return 0.0 + + self.assertRaises(IndexError, victim.__setitem__, 1, Float()) + self.assertEqual(len(victim), 0) + + if __name__ == "__main__": unittest.main()