diff options
Diffstat (limited to 'Lib/test/test_array.py')
-rwxr-xr-x | Lib/test/test_array.py | 267 |
1 files changed, 242 insertions, 25 deletions
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 62997d7..5190c35 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1,21 +1,28 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 """Test the arraymodule. Roger E. Masse """ import unittest from test import support -from weakref import proxy -import array, io, math -from pickle import loads, dumps, HIGHEST_PROTOCOL +import weakref +import pickle import operator +import io +import math +import struct +import warnings + +import array +from array import _array_reconstructor as array_reconstructor + class ArraySubclass(array.array): pass class ArraySubclassWithKwargs(array.array): def __init__(self, typecode, newarg=None): - array.array.__init__(self, typecode) + array.array.__init__(self) tests = [] # list to accumulate all tests typecodes = "ubBhHiIlLfd" @@ -30,6 +37,137 @@ class BadConstructorTest(unittest.TestCase): tests.append(BadConstructorTest) +# Machine format codes. +# +# Search for "enum machine_format_code" in Modules/arraymodule.c to get the +# authoritative values. +UNKNOWN_FORMAT = -1 +UNSIGNED_INT8 = 0 +SIGNED_INT8 = 1 +UNSIGNED_INT16_LE = 2 +UNSIGNED_INT16_BE = 3 +SIGNED_INT16_LE = 4 +SIGNED_INT16_BE = 5 +UNSIGNED_INT32_LE = 6 +UNSIGNED_INT32_BE = 7 +SIGNED_INT32_LE = 8 +SIGNED_INT32_BE = 9 +UNSIGNED_INT64_LE = 10 +UNSIGNED_INT64_BE = 11 +SIGNED_INT64_LE = 12 +SIGNED_INT64_BE = 13 +IEEE_754_FLOAT_LE = 14 +IEEE_754_FLOAT_BE = 15 +IEEE_754_DOUBLE_LE = 16 +IEEE_754_DOUBLE_BE = 17 +UTF16_LE = 18 +UTF16_BE = 19 +UTF32_LE = 20 +UTF32_BE = 21 + +class ArrayReconstructorTest(unittest.TestCase): + + def test_error(self): + self.assertRaises(TypeError, array_reconstructor, + "", "b", 0, b"") + self.assertRaises(TypeError, array_reconstructor, + str, "b", 0, b"") + self.assertRaises(TypeError, array_reconstructor, + array.array, "b", '', b"") + self.assertRaises(TypeError, array_reconstructor, + array.array, "b", 0, "") + self.assertRaises(ValueError, array_reconstructor, + array.array, "?", 0, b"") + self.assertRaises(ValueError, array_reconstructor, + array.array, "b", UNKNOWN_FORMAT, b"") + self.assertRaises(ValueError, array_reconstructor, + array.array, "b", 22, b"") + self.assertRaises(ValueError, array_reconstructor, + array.array, "d", 16, b"a") + + def test_numbers(self): + testcases = ( + (['B', 'H', 'I', 'L'], UNSIGNED_INT8, '=BBBB', + [0x80, 0x7f, 0, 0xff]), + (['b', 'h', 'i', 'l'], SIGNED_INT8, '=bbb', + [-0x80, 0x7f, 0]), + (['H', 'I', 'L'], UNSIGNED_INT16_LE, '<HHHH', + [0x8000, 0x7fff, 0, 0xffff]), + (['H', 'I', 'L'], UNSIGNED_INT16_BE, '>HHHH', + [0x8000, 0x7fff, 0, 0xffff]), + (['h', 'i', 'l'], SIGNED_INT16_LE, '<hhh', + [-0x8000, 0x7fff, 0]), + (['h', 'i', 'l'], SIGNED_INT16_BE, '>hhh', + [-0x8000, 0x7fff, 0]), + (['I', 'L'], UNSIGNED_INT32_LE, '<IIII', + [1<<31, (1<<31)-1, 0, (1<<32)-1]), + (['I', 'L'], UNSIGNED_INT32_BE, '>IIII', + [1<<31, (1<<31)-1, 0, (1<<32)-1]), + (['i', 'l'], SIGNED_INT32_LE, '<iii', + [-1<<31, (1<<31)-1, 0]), + (['i', 'l'], SIGNED_INT32_BE, '>iii', + [-1<<31, (1<<31)-1, 0]), + (['L'], UNSIGNED_INT64_LE, '<QQQQ', + [1<<31, (1<<31)-1, 0, (1<<32)-1]), + (['L'], UNSIGNED_INT64_BE, '>QQQQ', + [1<<31, (1<<31)-1, 0, (1<<32)-1]), + (['l'], SIGNED_INT64_LE, '<qqq', + [-1<<31, (1<<31)-1, 0]), + (['l'], SIGNED_INT64_BE, '>qqq', + [-1<<31, (1<<31)-1, 0]), + # The following tests for INT64 will raise an OverflowError + # when run on a 32-bit machine. The tests are simply skipped + # in that case. + (['L'], UNSIGNED_INT64_LE, '<QQQQ', + [1<<63, (1<<63)-1, 0, (1<<64)-1]), + (['L'], UNSIGNED_INT64_BE, '>QQQQ', + [1<<63, (1<<63)-1, 0, (1<<64)-1]), + (['l'], SIGNED_INT64_LE, '<qqq', + [-1<<63, (1<<63)-1, 0]), + (['l'], SIGNED_INT64_BE, '>qqq', + [-1<<63, (1<<63)-1, 0]), + (['f'], IEEE_754_FLOAT_LE, '<ffff', + [16711938.0, float('inf'), float('-inf'), -0.0]), + (['f'], IEEE_754_FLOAT_BE, '>ffff', + [16711938.0, float('inf'), float('-inf'), -0.0]), + (['d'], IEEE_754_DOUBLE_LE, '<dddd', + [9006104071832581.0, float('inf'), float('-inf'), -0.0]), + (['d'], IEEE_754_DOUBLE_BE, '>dddd', + [9006104071832581.0, float('inf'), float('-inf'), -0.0]) + ) + for testcase in testcases: + valid_typecodes, mformat_code, struct_fmt, values = testcase + arraystr = struct.pack(struct_fmt, *values) + for typecode in valid_typecodes: + try: + a = array.array(typecode, values) + except OverflowError: + continue # Skip this test case. + b = array_reconstructor( + array.array, typecode, mformat_code, arraystr) + self.assertEqual(a, b, + msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase)) + + 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"), + (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)) + + +tests.append(ArrayReconstructorTest) + + class BaseTest(unittest.TestCase): # Required class attributes (provided by subclasses # typecode: the typecode to test @@ -64,10 +202,10 @@ class BaseTest(unittest.TestCase): a = array.array(self.typecode, self.example) self.assertRaises(TypeError, a.buffer_info, 42) bi = a.buffer_info() - self.assertTrue(isinstance(bi, tuple)) + self.assertIsInstance(bi, tuple) self.assertEqual(len(bi), 2) - self.assertTrue(isinstance(bi[0], int)) - self.assertTrue(isinstance(bi[1], int)) + self.assertIsInstance(bi[0], int) + self.assertIsInstance(bi[1], int) self.assertEqual(bi[1], len(a)) def test_byteswap(self): @@ -97,31 +235,38 @@ class BaseTest(unittest.TestCase): self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) + def test_reduce_ex(self): + a = array.array(self.typecode, self.example) + for protocol in range(3): + self.assertIs(a.__reduce_ex__(protocol)[0], array.array) + for protocol in range(3, pickle.HIGHEST_PROTOCOL): + self.assertIs(a.__reduce_ex__(protocol)[0], array_reconstructor) + def test_pickle(self): - for protocol in range(HIGHEST_PROTOCOL + 1): + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): a = array.array(self.typecode, self.example) - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) a = ArraySubclass(self.typecode, self.example) a.x = 10 - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) self.assertEqual(a.x, b.x) self.assertEqual(type(a), type(b)) def test_pickle_for_empty_array(self): - for protocol in range(HIGHEST_PROTOCOL + 1): + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): a = array.array(self.typecode) - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) a = ArraySubclass(self.typecode) a.x = 10 - b = loads(dumps(a, protocol)) + b = pickle.loads(pickle.dumps(a, protocol)) self.assertNotEqual(id(a), id(b)) self.assertEqual(a, b) self.assertEqual(a.x, b.x) @@ -193,6 +338,25 @@ class BaseTest(unittest.TestCase): f.close() support.unlink(support.TESTFN) + def test_filewrite(self): + a = array.array(self.typecode, 2*self.example) + f = open(support.TESTFN, 'wb') + try: + f.write(a) + f.close() + b = array.array(self.typecode) + f = open(support.TESTFN, 'rb') + b.fromfile(f, len(self.example)) + self.assertEqual(b, array.array(self.typecode, self.example)) + self.assertNotEqual(a, b) + b.fromfile(f, len(self.example)) + self.assertEqual(a, b) + f.close() + finally: + if not f.closed: + f.close() + support.unlink(support.TESTFN) + def test_tofromlist(self): a = array.array(self.typecode, 2*self.example) b = array.array(self.typecode) @@ -204,15 +368,40 @@ class BaseTest(unittest.TestCase): self.assertEqual(a, b) def test_tofromstring(self): + nb_warnings = 4 + with warnings.catch_warnings(record=True) as r: + warnings.filterwarnings("always", + message=r"(to|from)string\(\) is deprecated", + category=DeprecationWarning) + a = array.array(self.typecode, 2*self.example) + b = array.array(self.typecode) + self.assertRaises(TypeError, a.tostring, 42) + self.assertRaises(TypeError, b.fromstring) + self.assertRaises(TypeError, b.fromstring, 42) + b.fromstring(a.tostring()) + self.assertEqual(a, b) + if a.itemsize>1: + self.assertRaises(ValueError, b.fromstring, "x") + nb_warnings += 1 + self.assertEqual(len(r), nb_warnings) + + def test_tofrombytes(self): a = array.array(self.typecode, 2*self.example) b = array.array(self.typecode) - self.assertRaises(TypeError, a.tostring, 42) - self.assertRaises(TypeError, b.fromstring) - self.assertRaises(TypeError, b.fromstring, 42) - b.fromstring(a.tostring()) + self.assertRaises(TypeError, a.tobytes, 42) + self.assertRaises(TypeError, b.frombytes) + self.assertRaises(TypeError, b.frombytes, 42) + b.frombytes(a.tobytes()) + c = array.array(self.typecode, bytearray(a.tobytes())) self.assertEqual(a, b) + self.assertEqual(a, c) if a.itemsize>1: - self.assertRaises(ValueError, b.fromstring, "x") + self.assertRaises(ValueError, b.frombytes, b"x") + + def test_fromarray(self): + a = array.array(self.typecode, self.example) + b = array.array(self.typecode, a) + self.assertEqual(a, b) def test_repr(self): a = array.array(self.typecode, 2*self.example) @@ -320,6 +509,12 @@ class BaseTest(unittest.TestCase): array.array(self.typecode) ) + a = 5 * array.array(self.typecode, self.example[:1]) + self.assertEqual( + a, + array.array(self.typecode, [a[0]] * 5) + ) + self.assertRaises(TypeError, a.__mul__, "bad") def test_imul(self): @@ -735,8 +930,8 @@ class BaseTest(unittest.TestCase): a = array.array(self.typecode, self.example) m = memoryview(a) expected = m.tobytes() - self.assertEqual(a.tostring(), expected) - self.assertEqual(a.tostring()[0], expected[0]) + self.assertEqual(a.tobytes(), expected) + self.assertEqual(a.tobytes()[0], expected[0]) # Resizing is forbidden when there are buffer exports. # For issue 4509, we also check after each error that # the array was not modified. @@ -750,7 +945,7 @@ class BaseTest(unittest.TestCase): self.assertEqual(m.tobytes(), expected) self.assertRaises(BufferError, a.fromlist, a.tolist()) self.assertEqual(m.tobytes(), expected) - self.assertRaises(BufferError, a.fromstring, a.tostring()) + self.assertRaises(BufferError, a.frombytes, a.tobytes()) self.assertEqual(m.tobytes(), expected) if self.typecode == 'u': self.assertRaises(BufferError, a.fromunicode, a.tounicode()) @@ -768,8 +963,8 @@ class BaseTest(unittest.TestCase): def test_weakref(self): s = array.array(self.typecode, self.example) - p = proxy(s) - self.assertEqual(p.tostring(), s.tostring()) + p = weakref.proxy(s) + self.assertEqual(p.tobytes(), s.tobytes()) s = None self.assertRaises(ReferenceError, len, p) @@ -923,6 +1118,11 @@ class NumberTest(BaseTest): self.assertRaises(AttributeError, setattr, a, "color", "blue") + def test_frombytearray(self): + a = array.array('b', range(10)) + b = array.array(self.typecode, a) + self.assertEqual(a, b) + class SignedNumberTest(NumberTest): example = [-1, 0, 1, 42, 0x7f] smallerexample = [-1, 0, 1, 42, 0x7e] @@ -947,6 +1147,23 @@ class UnsignedNumberTest(NumberTest): upper = int(pow(2, a.itemsize * 8)) - 1 self.check_overflow(lower, upper) + def test_bytes_extend(self): + s = bytes(self.example) + + a = array.array(self.typecode, self.example) + a.extend(s) + self.assertEqual( + a, + array.array(self.typecode, self.example+self.example) + ) + + a = array.array(self.typecode, self.example) + a.extend(bytearray(reversed(s))) + self.assertEqual( + a, + array.array(self.typecode, self.example+self.example[::-1]) + ) + class ByteTest(SignedNumberTest): typecode = 'b' @@ -1009,7 +1226,7 @@ class FPTest(NumberTest): # On alphas treating the byte swapped bit patters as # floats/doubles results in floating point exceptions # => compare the 8bit string values instead - self.assertNotEqual(a.tostring(), b.tostring()) + self.assertNotEqual(a.tobytes(), b.tobytes()) b.byteswap() self.assertEqual(a, b) |