1"""Test the arraymodule.
2   Roger E. Masse
3"""
4
5import collections.abc
6import unittest
7from test import support
8from test.support import os_helper
9from test.support import _2G
10import weakref
11import pickle
12import operator
13import struct
14import sys
15
16import array
17from array import _array_reconstructor as array_reconstructor
18
19sizeof_wchar = array.array('u').itemsize
20
21
22class ArraySubclass(array.array):
23    pass
24
25class ArraySubclassWithKwargs(array.array):
26    def __init__(self, typecode, newarg=None):
27        array.array.__init__(self)
28
29typecodes = 'ubBhHiIlLfdqQ'
30
31class MiscTest(unittest.TestCase):
32
33    def test_array_is_sequence(self):
34        self.assertIsInstance(array.array("B"), collections.abc.MutableSequence)
35        self.assertIsInstance(array.array("B"), collections.abc.Reversible)
36
37    def test_bad_constructor(self):
38        self.assertRaises(TypeError, array.array)
39        self.assertRaises(TypeError, array.array, spam=42)
40        self.assertRaises(TypeError, array.array, 'xx')
41        self.assertRaises(ValueError, array.array, 'x')
42
43    @support.cpython_only
44    def test_disallow_instantiation(self):
45        my_array = array.array("I")
46        support.check_disallow_instantiation(
47            self, type(iter(my_array)), my_array
48        )
49
50    @support.cpython_only
51    def test_immutable(self):
52        # bpo-43908: check that array.array is immutable
53        with self.assertRaises(TypeError):
54            array.array.foo = 1
55
56    def test_empty(self):
57        # Exercise code for handling zero-length arrays
58        a = array.array('B')
59        a[:] = a
60        self.assertEqual(len(a), 0)
61        self.assertEqual(len(a + a), 0)
62        self.assertEqual(len(a * 3), 0)
63        a += a
64        self.assertEqual(len(a), 0)
65
66
67# Machine format codes.
68#
69# Search for "enum machine_format_code" in Modules/arraymodule.c to get the
70# authoritative values.
71UNKNOWN_FORMAT = -1
72UNSIGNED_INT8 = 0
73SIGNED_INT8 = 1
74UNSIGNED_INT16_LE = 2
75UNSIGNED_INT16_BE = 3
76SIGNED_INT16_LE = 4
77SIGNED_INT16_BE = 5
78UNSIGNED_INT32_LE = 6
79UNSIGNED_INT32_BE = 7
80SIGNED_INT32_LE = 8
81SIGNED_INT32_BE = 9
82UNSIGNED_INT64_LE = 10
83UNSIGNED_INT64_BE = 11
84SIGNED_INT64_LE = 12
85SIGNED_INT64_BE = 13
86IEEE_754_FLOAT_LE = 14
87IEEE_754_FLOAT_BE = 15
88IEEE_754_DOUBLE_LE = 16
89IEEE_754_DOUBLE_BE = 17
90UTF16_LE = 18
91UTF16_BE = 19
92UTF32_LE = 20
93UTF32_BE = 21
94
95class ArrayReconstructorTest(unittest.TestCase):
96
97    def test_error(self):
98        self.assertRaises(TypeError, array_reconstructor,
99                          "", "b", 0, b"")
100        self.assertRaises(TypeError, array_reconstructor,
101                          str, "b", 0, b"")
102        self.assertRaises(TypeError, array_reconstructor,
103                          array.array, "b", '', b"")
104        self.assertRaises(TypeError, array_reconstructor,
105                          array.array, "b", 0, "")
106        self.assertRaises(ValueError, array_reconstructor,
107                          array.array, "?", 0, b"")
108        self.assertRaises(ValueError, array_reconstructor,
109                          array.array, "b", UNKNOWN_FORMAT, b"")
110        self.assertRaises(ValueError, array_reconstructor,
111                          array.array, "b", 22, b"")
112        self.assertRaises(ValueError, array_reconstructor,
113                          array.array, "d", 16, b"a")
114
115    def test_numbers(self):
116        testcases = (
117            (['B', 'H', 'I', 'L'], UNSIGNED_INT8, '=BBBB',
118             [0x80, 0x7f, 0, 0xff]),
119            (['b', 'h', 'i', 'l'], SIGNED_INT8, '=bbb',
120             [-0x80, 0x7f, 0]),
121            (['H', 'I', 'L'], UNSIGNED_INT16_LE, '<HHHH',
122             [0x8000, 0x7fff, 0, 0xffff]),
123            (['H', 'I', 'L'], UNSIGNED_INT16_BE, '>HHHH',
124             [0x8000, 0x7fff, 0, 0xffff]),
125            (['h', 'i', 'l'], SIGNED_INT16_LE, '<hhh',
126             [-0x8000, 0x7fff, 0]),
127            (['h', 'i', 'l'], SIGNED_INT16_BE, '>hhh',
128             [-0x8000, 0x7fff, 0]),
129            (['I', 'L'], UNSIGNED_INT32_LE, '<IIII',
130             [1<<31, (1<<31)-1, 0, (1<<32)-1]),
131            (['I', 'L'], UNSIGNED_INT32_BE, '>IIII',
132             [1<<31, (1<<31)-1, 0, (1<<32)-1]),
133            (['i', 'l'], SIGNED_INT32_LE, '<iii',
134             [-1<<31, (1<<31)-1, 0]),
135            (['i', 'l'], SIGNED_INT32_BE, '>iii',
136             [-1<<31, (1<<31)-1, 0]),
137            (['L'], UNSIGNED_INT64_LE, '<QQQQ',
138             [1<<31, (1<<31)-1, 0, (1<<32)-1]),
139            (['L'], UNSIGNED_INT64_BE, '>QQQQ',
140             [1<<31, (1<<31)-1, 0, (1<<32)-1]),
141            (['l'], SIGNED_INT64_LE, '<qqq',
142             [-1<<31, (1<<31)-1, 0]),
143            (['l'], SIGNED_INT64_BE, '>qqq',
144             [-1<<31, (1<<31)-1, 0]),
145            # The following tests for INT64 will raise an OverflowError
146            # when run on a 32-bit machine. The tests are simply skipped
147            # in that case.
148            (['L'], UNSIGNED_INT64_LE, '<QQQQ',
149             [1<<63, (1<<63)-1, 0, (1<<64)-1]),
150            (['L'], UNSIGNED_INT64_BE, '>QQQQ',
151             [1<<63, (1<<63)-1, 0, (1<<64)-1]),
152            (['l'], SIGNED_INT64_LE, '<qqq',
153             [-1<<63, (1<<63)-1, 0]),
154            (['l'], SIGNED_INT64_BE, '>qqq',
155             [-1<<63, (1<<63)-1, 0]),
156            (['f'], IEEE_754_FLOAT_LE, '<ffff',
157             [16711938.0, float('inf'), float('-inf'), -0.0]),
158            (['f'], IEEE_754_FLOAT_BE, '>ffff',
159             [16711938.0, float('inf'), float('-inf'), -0.0]),
160            (['d'], IEEE_754_DOUBLE_LE, '<dddd',
161             [9006104071832581.0, float('inf'), float('-inf'), -0.0]),
162            (['d'], IEEE_754_DOUBLE_BE, '>dddd',
163             [9006104071832581.0, float('inf'), float('-inf'), -0.0])
164        )
165        for testcase in testcases:
166            valid_typecodes, mformat_code, struct_fmt, values = testcase
167            arraystr = struct.pack(struct_fmt, *values)
168            for typecode in valid_typecodes:
169                try:
170                    a = array.array(typecode, values)
171                except OverflowError:
172                    continue  # Skip this test case.
173                b = array_reconstructor(
174                    array.array, typecode, mformat_code, arraystr)
175                self.assertEqual(a, b,
176                    msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase))
177
178    def test_unicode(self):
179        teststr = "Bonne Journ\xe9e \U0002030a\U00020347"
180        testcases = (
181            (UTF16_LE, "UTF-16-LE"),
182            (UTF16_BE, "UTF-16-BE"),
183            (UTF32_LE, "UTF-32-LE"),
184            (UTF32_BE, "UTF-32-BE")
185        )
186        for testcase in testcases:
187            mformat_code, encoding = testcase
188            a = array.array('u', teststr)
189            b = array_reconstructor(
190                array.array, 'u', mformat_code, teststr.encode(encoding))
191            self.assertEqual(a, b,
192                msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase))
193
194
195class BaseTest:
196    # Required class attributes (provided by subclasses
197    # typecode: the typecode to test
198    # example: an initializer usable in the constructor for this type
199    # smallerexample: the same length as example, but smaller
200    # biggerexample: the same length as example, but bigger
201    # outside: An entry that is not in example
202    # minitemsize: the minimum guaranteed itemsize
203
204    def assertEntryEqual(self, entry1, entry2):
205        self.assertEqual(entry1, entry2)
206
207    def badtypecode(self):
208        # Return a typecode that is different from our own
209        return typecodes[(typecodes.index(self.typecode)+1) % len(typecodes)]
210
211    def test_constructor(self):
212        a = array.array(self.typecode)
213        self.assertEqual(a.typecode, self.typecode)
214        self.assertGreaterEqual(a.itemsize, self.minitemsize)
215        self.assertRaises(TypeError, array.array, self.typecode, None)
216
217    def test_len(self):
218        a = array.array(self.typecode)
219        a.append(self.example[0])
220        self.assertEqual(len(a), 1)
221
222        a = array.array(self.typecode, self.example)
223        self.assertEqual(len(a), len(self.example))
224
225    def test_buffer_info(self):
226        a = array.array(self.typecode, self.example)
227        self.assertRaises(TypeError, a.buffer_info, 42)
228        bi = a.buffer_info()
229        self.assertIsInstance(bi, tuple)
230        self.assertEqual(len(bi), 2)
231        self.assertIsInstance(bi[0], int)
232        self.assertIsInstance(bi[1], int)
233        self.assertEqual(bi[1], len(a))
234
235    def test_byteswap(self):
236        if self.typecode == 'u':
237            example = '\U00100100'
238        else:
239            example = self.example
240        a = array.array(self.typecode, example)
241        self.assertRaises(TypeError, a.byteswap, 42)
242        if a.itemsize in (1, 2, 4, 8):
243            b = array.array(self.typecode, example)
244            b.byteswap()
245            if a.itemsize==1:
246                self.assertEqual(a, b)
247            else:
248                self.assertNotEqual(a, b)
249            b.byteswap()
250            self.assertEqual(a, b)
251
252    def test_copy(self):
253        import copy
254        a = array.array(self.typecode, self.example)
255        b = copy.copy(a)
256        self.assertNotEqual(id(a), id(b))
257        self.assertEqual(a, b)
258
259    def test_deepcopy(self):
260        import copy
261        a = array.array(self.typecode, self.example)
262        b = copy.deepcopy(a)
263        self.assertNotEqual(id(a), id(b))
264        self.assertEqual(a, b)
265
266    def test_reduce_ex(self):
267        a = array.array(self.typecode, self.example)
268        for protocol in range(3):
269            self.assertIs(a.__reduce_ex__(protocol)[0], array.array)
270        for protocol in range(3, pickle.HIGHEST_PROTOCOL + 1):
271            self.assertIs(a.__reduce_ex__(protocol)[0], array_reconstructor)
272
273    def test_pickle(self):
274        for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
275            a = array.array(self.typecode, self.example)
276            b = pickle.loads(pickle.dumps(a, protocol))
277            self.assertNotEqual(id(a), id(b))
278            self.assertEqual(a, b)
279
280            a = ArraySubclass(self.typecode, self.example)
281            a.x = 10
282            b = pickle.loads(pickle.dumps(a, protocol))
283            self.assertNotEqual(id(a), id(b))
284            self.assertEqual(a, b)
285            self.assertEqual(a.x, b.x)
286            self.assertEqual(type(a), type(b))
287
288    def test_pickle_for_empty_array(self):
289        for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
290            a = array.array(self.typecode)
291            b = pickle.loads(pickle.dumps(a, protocol))
292            self.assertNotEqual(id(a), id(b))
293            self.assertEqual(a, b)
294
295            a = ArraySubclass(self.typecode)
296            a.x = 10
297            b = pickle.loads(pickle.dumps(a, protocol))
298            self.assertNotEqual(id(a), id(b))
299            self.assertEqual(a, b)
300            self.assertEqual(a.x, b.x)
301            self.assertEqual(type(a), type(b))
302
303    def test_iterator_pickle(self):
304        orig = array.array(self.typecode, self.example)
305        data = list(orig)
306        data2 = data[::-1]
307        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
308            # initial iterator
309            itorig = iter(orig)
310            d = pickle.dumps((itorig, orig), proto)
311            it, a = pickle.loads(d)
312            a.fromlist(data2)
313            self.assertEqual(type(it), type(itorig))
314            self.assertEqual(list(it), data + data2)
315
316            # running iterator
317            next(itorig)
318            d = pickle.dumps((itorig, orig), proto)
319            it, a = pickle.loads(d)
320            a.fromlist(data2)
321            self.assertEqual(type(it), type(itorig))
322            self.assertEqual(list(it), data[1:] + data2)
323
324            # empty iterator
325            for i in range(1, len(data)):
326                next(itorig)
327            d = pickle.dumps((itorig, orig), proto)
328            it, a = pickle.loads(d)
329            a.fromlist(data2)
330            self.assertEqual(type(it), type(itorig))
331            self.assertEqual(list(it), data2)
332
333            # exhausted iterator
334            self.assertRaises(StopIteration, next, itorig)
335            d = pickle.dumps((itorig, orig), proto)
336            it, a = pickle.loads(d)
337            a.fromlist(data2)
338            self.assertEqual(list(it), [])
339
340    def test_exhausted_iterator(self):
341        a = array.array(self.typecode, self.example)
342        self.assertEqual(list(a), list(self.example))
343        exhit = iter(a)
344        empit = iter(a)
345        for x in exhit:  # exhaust the iterator
346            next(empit)  # not exhausted
347        a.append(self.outside)
348        self.assertEqual(list(exhit), [])
349        self.assertEqual(list(empit), [self.outside])
350        self.assertEqual(list(a), list(self.example) + [self.outside])
351
352    def test_reverse_iterator(self):
353        a = array.array(self.typecode, self.example)
354        self.assertEqual(list(a), list(self.example))
355        self.assertEqual(list(reversed(a)), list(iter(a))[::-1])
356
357    def test_reverse_iterator_picking(self):
358        orig = array.array(self.typecode, self.example)
359        data = list(orig)
360        data2 = [self.outside] + data
361        rev_data = data[len(data)-2::-1] + [self.outside]
362        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
363            # initial iterator
364            itorig = reversed(orig)
365            d = pickle.dumps((itorig, orig), proto)
366            it, a = pickle.loads(d)
367            a.insert(0, self.outside)
368            self.assertEqual(type(it), type(itorig))
369            self.assertEqual(list(it), rev_data)
370            self.assertEqual(list(a), data2)
371
372            # running iterator
373            next(itorig)
374            d = pickle.dumps((itorig, orig), proto)
375            it, a = pickle.loads(d)
376            a.insert(0, self.outside)
377            self.assertEqual(type(it), type(itorig))
378            self.assertEqual(list(it), rev_data[1:])
379            self.assertEqual(list(a), data2)
380
381            # empty iterator
382            for i in range(1, len(data)):
383                next(itorig)
384            d = pickle.dumps((itorig, orig), proto)
385            it, a = pickle.loads(d)
386            a.insert(0, self.outside)
387            self.assertEqual(type(it), type(itorig))
388            self.assertEqual(list(it), [])
389            self.assertEqual(list(a), data2)
390
391            # exhausted iterator
392            self.assertRaises(StopIteration, next, itorig)
393            d = pickle.dumps((itorig, orig), proto)
394            it, a = pickle.loads(d)
395            a.insert(0, self.outside)
396            self.assertEqual(list(it), [])
397            self.assertEqual(list(a), data2)
398
399    def test_exhausted_reverse_iterator(self):
400        a = array.array(self.typecode, self.example)
401        self.assertEqual(list(a), list(self.example))
402        exhit = reversed(a)
403        empit = reversed(a)
404        for x in exhit:  # exhaust the iterator
405            next(empit)  # Pointing past the 0th position.
406        a.insert(0, self.outside)
407        self.assertEqual(list(exhit), [])
408        # The iterator index points past the 0th position so inserting
409        # an element in the beginning does not make it appear.
410        self.assertEqual(list(empit), [])
411        self.assertEqual(list(a), [self.outside] + list(self.example))
412
413    def test_insert(self):
414        a = array.array(self.typecode, self.example)
415        a.insert(0, self.example[0])
416        self.assertEqual(len(a), 1+len(self.example))
417        self.assertEqual(a[0], a[1])
418        self.assertRaises(TypeError, a.insert)
419        self.assertRaises(TypeError, a.insert, None)
420        self.assertRaises(TypeError, a.insert, 0, None)
421
422        a = array.array(self.typecode, self.example)
423        a.insert(-1, self.example[0])
424        self.assertEqual(
425            a,
426            array.array(
427                self.typecode,
428                self.example[:-1] + self.example[:1] + self.example[-1:]
429            )
430        )
431
432        a = array.array(self.typecode, self.example)
433        a.insert(-1000, self.example[0])
434        self.assertEqual(
435            a,
436            array.array(self.typecode, self.example[:1] + self.example)
437        )
438
439        a = array.array(self.typecode, self.example)
440        a.insert(1000, self.example[0])
441        self.assertEqual(
442            a,
443            array.array(self.typecode, self.example + self.example[:1])
444        )
445
446    def test_tofromfile(self):
447        a = array.array(self.typecode, 2*self.example)
448        self.assertRaises(TypeError, a.tofile)
449        os_helper.unlink(os_helper.TESTFN)
450        f = open(os_helper.TESTFN, 'wb')
451        try:
452            a.tofile(f)
453            f.close()
454            b = array.array(self.typecode)
455            f = open(os_helper.TESTFN, 'rb')
456            self.assertRaises(TypeError, b.fromfile)
457            b.fromfile(f, len(self.example))
458            self.assertEqual(b, array.array(self.typecode, self.example))
459            self.assertNotEqual(a, b)
460            self.assertRaises(EOFError, b.fromfile, f, len(self.example)+1)
461            self.assertEqual(a, b)
462            f.close()
463        finally:
464            if not f.closed:
465                f.close()
466            os_helper.unlink(os_helper.TESTFN)
467
468    def test_fromfile_ioerror(self):
469        # Issue #5395: Check if fromfile raises a proper OSError
470        # instead of EOFError.
471        a = array.array(self.typecode)
472        f = open(os_helper.TESTFN, 'wb')
473        try:
474            self.assertRaises(OSError, a.fromfile, f, len(self.example))
475        finally:
476            f.close()
477            os_helper.unlink(os_helper.TESTFN)
478
479    def test_filewrite(self):
480        a = array.array(self.typecode, 2*self.example)
481        f = open(os_helper.TESTFN, 'wb')
482        try:
483            f.write(a)
484            f.close()
485            b = array.array(self.typecode)
486            f = open(os_helper.TESTFN, 'rb')
487            b.fromfile(f, len(self.example))
488            self.assertEqual(b, array.array(self.typecode, self.example))
489            self.assertNotEqual(a, b)
490            b.fromfile(f, len(self.example))
491            self.assertEqual(a, b)
492            f.close()
493        finally:
494            if not f.closed:
495                f.close()
496            os_helper.unlink(os_helper.TESTFN)
497
498    def test_tofromlist(self):
499        a = array.array(self.typecode, 2*self.example)
500        b = array.array(self.typecode)
501        self.assertRaises(TypeError, a.tolist, 42)
502        self.assertRaises(TypeError, b.fromlist)
503        self.assertRaises(TypeError, b.fromlist, 42)
504        self.assertRaises(TypeError, b.fromlist, [None])
505        b.fromlist(a.tolist())
506        self.assertEqual(a, b)
507
508    def test_tofrombytes(self):
509        a = array.array(self.typecode, 2*self.example)
510        b = array.array(self.typecode)
511        self.assertRaises(TypeError, a.tobytes, 42)
512        self.assertRaises(TypeError, b.frombytes)
513        self.assertRaises(TypeError, b.frombytes, 42)
514        b.frombytes(a.tobytes())
515        c = array.array(self.typecode, bytearray(a.tobytes()))
516        self.assertEqual(a, b)
517        self.assertEqual(a, c)
518        if a.itemsize>1:
519            self.assertRaises(ValueError, b.frombytes, b"x")
520
521    def test_fromarray(self):
522        a = array.array(self.typecode, self.example)
523        b = array.array(self.typecode, a)
524        self.assertEqual(a, b)
525
526    def test_repr(self):
527        a = array.array(self.typecode, 2*self.example)
528        self.assertEqual(a, eval(repr(a), {"array": array.array}))
529
530        a = array.array(self.typecode)
531        self.assertEqual(repr(a), "array('%s')" % self.typecode)
532
533    def test_str(self):
534        a = array.array(self.typecode, 2*self.example)
535        str(a)
536
537    def test_cmp(self):
538        a = array.array(self.typecode, self.example)
539        self.assertIs(a == 42, False)
540        self.assertIs(a != 42, True)
541
542        self.assertIs(a == a, True)
543        self.assertIs(a != a, False)
544        self.assertIs(a < a, False)
545        self.assertIs(a <= a, True)
546        self.assertIs(a > a, False)
547        self.assertIs(a >= a, True)
548
549        al = array.array(self.typecode, self.smallerexample)
550        ab = array.array(self.typecode, self.biggerexample)
551
552        self.assertIs(a == 2*a, False)
553        self.assertIs(a != 2*a, True)
554        self.assertIs(a < 2*a, True)
555        self.assertIs(a <= 2*a, True)
556        self.assertIs(a > 2*a, False)
557        self.assertIs(a >= 2*a, False)
558
559        self.assertIs(a == al, False)
560        self.assertIs(a != al, True)
561        self.assertIs(a < al, False)
562        self.assertIs(a <= al, False)
563        self.assertIs(a > al, True)
564        self.assertIs(a >= al, True)
565
566        self.assertIs(a == ab, False)
567        self.assertIs(a != ab, True)
568        self.assertIs(a < ab, True)
569        self.assertIs(a <= ab, True)
570        self.assertIs(a > ab, False)
571        self.assertIs(a >= ab, False)
572
573    def test_add(self):
574        a = array.array(self.typecode, self.example) \
575            + array.array(self.typecode, self.example[::-1])
576        self.assertEqual(
577            a,
578            array.array(self.typecode, self.example + self.example[::-1])
579        )
580
581        b = array.array(self.badtypecode())
582        self.assertRaises(TypeError, a.__add__, b)
583
584        self.assertRaises(TypeError, a.__add__, "bad")
585
586    def test_iadd(self):
587        a = array.array(self.typecode, self.example[::-1])
588        b = a
589        a += array.array(self.typecode, 2*self.example)
590        self.assertIs(a, b)
591        self.assertEqual(
592            a,
593            array.array(self.typecode, self.example[::-1]+2*self.example)
594        )
595        a = array.array(self.typecode, self.example)
596        a += a
597        self.assertEqual(
598            a,
599            array.array(self.typecode, self.example + self.example)
600        )
601
602        b = array.array(self.badtypecode())
603        self.assertRaises(TypeError, a.__add__, b)
604
605        self.assertRaises(TypeError, a.__iadd__, "bad")
606
607    def test_mul(self):
608        a = 5*array.array(self.typecode, self.example)
609        self.assertEqual(
610            a,
611            array.array(self.typecode, 5*self.example)
612        )
613
614        a = array.array(self.typecode, self.example)*5
615        self.assertEqual(
616            a,
617            array.array(self.typecode, self.example*5)
618        )
619
620        a = 0*array.array(self.typecode, self.example)
621        self.assertEqual(
622            a,
623            array.array(self.typecode)
624        )
625
626        a = (-1)*array.array(self.typecode, self.example)
627        self.assertEqual(
628            a,
629            array.array(self.typecode)
630        )
631
632        a = 5 * array.array(self.typecode, self.example[:1])
633        self.assertEqual(
634            a,
635            array.array(self.typecode, [a[0]] * 5)
636        )
637
638        self.assertRaises(TypeError, a.__mul__, "bad")
639
640    def test_imul(self):
641        a = array.array(self.typecode, self.example)
642        b = a
643
644        a *= 5
645        self.assertIs(a, b)
646        self.assertEqual(
647            a,
648            array.array(self.typecode, 5*self.example)
649        )
650
651        a *= 0
652        self.assertIs(a, b)
653        self.assertEqual(a, array.array(self.typecode))
654
655        a *= 1000
656        self.assertIs(a, b)
657        self.assertEqual(a, array.array(self.typecode))
658
659        a *= -1
660        self.assertIs(a, b)
661        self.assertEqual(a, array.array(self.typecode))
662
663        a = array.array(self.typecode, self.example)
664        a *= -1
665        self.assertEqual(a, array.array(self.typecode))
666
667        self.assertRaises(TypeError, a.__imul__, "bad")
668
669    def test_getitem(self):
670        a = array.array(self.typecode, self.example)
671        self.assertEntryEqual(a[0], self.example[0])
672        self.assertEntryEqual(a[0], self.example[0])
673        self.assertEntryEqual(a[-1], self.example[-1])
674        self.assertEntryEqual(a[-1], self.example[-1])
675        self.assertEntryEqual(a[len(self.example)-1], self.example[-1])
676        self.assertEntryEqual(a[-len(self.example)], self.example[0])
677        self.assertRaises(TypeError, a.__getitem__)
678        self.assertRaises(IndexError, a.__getitem__, len(self.example))
679        self.assertRaises(IndexError, a.__getitem__, -len(self.example)-1)
680
681    def test_setitem(self):
682        a = array.array(self.typecode, self.example)
683        a[0] = a[-1]
684        self.assertEntryEqual(a[0], a[-1])
685
686        a = array.array(self.typecode, self.example)
687        a[0] = a[-1]
688        self.assertEntryEqual(a[0], a[-1])
689
690        a = array.array(self.typecode, self.example)
691        a[-1] = a[0]
692        self.assertEntryEqual(a[0], a[-1])
693
694        a = array.array(self.typecode, self.example)
695        a[-1] = a[0]
696        self.assertEntryEqual(a[0], a[-1])
697
698        a = array.array(self.typecode, self.example)
699        a[len(self.example)-1] = a[0]
700        self.assertEntryEqual(a[0], a[-1])
701
702        a = array.array(self.typecode, self.example)
703        a[-len(self.example)] = a[-1]
704        self.assertEntryEqual(a[0], a[-1])
705
706        self.assertRaises(TypeError, a.__setitem__)
707        self.assertRaises(TypeError, a.__setitem__, None)
708        self.assertRaises(TypeError, a.__setitem__, 0, None)
709        self.assertRaises(
710            IndexError,
711            a.__setitem__,
712            len(self.example), self.example[0]
713        )
714        self.assertRaises(
715            IndexError,
716            a.__setitem__,
717            -len(self.example)-1, self.example[0]
718        )
719
720    def test_delitem(self):
721        a = array.array(self.typecode, self.example)
722        del a[0]
723        self.assertEqual(
724            a,
725            array.array(self.typecode, self.example[1:])
726        )
727
728        a = array.array(self.typecode, self.example)
729        del a[-1]
730        self.assertEqual(
731            a,
732            array.array(self.typecode, self.example[:-1])
733        )
734
735        a = array.array(self.typecode, self.example)
736        del a[len(self.example)-1]
737        self.assertEqual(
738            a,
739            array.array(self.typecode, self.example[:-1])
740        )
741
742        a = array.array(self.typecode, self.example)
743        del a[-len(self.example)]
744        self.assertEqual(
745            a,
746            array.array(self.typecode, self.example[1:])
747        )
748
749        self.assertRaises(TypeError, a.__delitem__)
750        self.assertRaises(TypeError, a.__delitem__, None)
751        self.assertRaises(IndexError, a.__delitem__, len(self.example))
752        self.assertRaises(IndexError, a.__delitem__, -len(self.example)-1)
753
754    def test_getslice(self):
755        a = array.array(self.typecode, self.example)
756        self.assertEqual(a[:], a)
757
758        self.assertEqual(
759            a[1:],
760            array.array(self.typecode, self.example[1:])
761        )
762
763        self.assertEqual(
764            a[:1],
765            array.array(self.typecode, self.example[:1])
766        )
767
768        self.assertEqual(
769            a[:-1],
770            array.array(self.typecode, self.example[:-1])
771        )
772
773        self.assertEqual(
774            a[-1:],
775            array.array(self.typecode, self.example[-1:])
776        )
777
778        self.assertEqual(
779            a[-1:-1],
780            array.array(self.typecode)
781        )
782
783        self.assertEqual(
784            a[2:1],
785            array.array(self.typecode)
786        )
787
788        self.assertEqual(
789            a[1000:],
790            array.array(self.typecode)
791        )
792        self.assertEqual(a[-1000:], a)
793        self.assertEqual(a[:1000], a)
794        self.assertEqual(
795            a[:-1000],
796            array.array(self.typecode)
797        )
798        self.assertEqual(a[-1000:1000], a)
799        self.assertEqual(
800            a[2000:1000],
801            array.array(self.typecode)
802        )
803
804    def test_extended_getslice(self):
805        # Test extended slicing by comparing with list slicing
806        # (Assumes list conversion works correctly, too)
807        a = array.array(self.typecode, self.example)
808        indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
809        for start in indices:
810            for stop in indices:
811                # Everything except the initial 0 (invalid step)
812                for step in indices[1:]:
813                    self.assertEqual(list(a[start:stop:step]),
814                                     list(a)[start:stop:step])
815
816    def test_setslice(self):
817        a = array.array(self.typecode, self.example)
818        a[:1] = a
819        self.assertEqual(
820            a,
821            array.array(self.typecode, self.example + self.example[1:])
822        )
823
824        a = array.array(self.typecode, self.example)
825        a[:-1] = a
826        self.assertEqual(
827            a,
828            array.array(self.typecode, self.example + self.example[-1:])
829        )
830
831        a = array.array(self.typecode, self.example)
832        a[-1:] = a
833        self.assertEqual(
834            a,
835            array.array(self.typecode, self.example[:-1] + self.example)
836        )
837
838        a = array.array(self.typecode, self.example)
839        a[1:] = a
840        self.assertEqual(
841            a,
842            array.array(self.typecode, self.example[:1] + self.example)
843        )
844
845        a = array.array(self.typecode, self.example)
846        a[1:-1] = a
847        self.assertEqual(
848            a,
849            array.array(
850                self.typecode,
851                self.example[:1] + self.example + self.example[-1:]
852            )
853        )
854
855        a = array.array(self.typecode, self.example)
856        a[1000:] = a
857        self.assertEqual(
858            a,
859            array.array(self.typecode, 2*self.example)
860        )
861
862        a = array.array(self.typecode, self.example)
863        a[-1000:] = a
864        self.assertEqual(
865            a,
866            array.array(self.typecode, self.example)
867        )
868
869        a = array.array(self.typecode, self.example)
870        a[:1000] = a
871        self.assertEqual(
872            a,
873            array.array(self.typecode, self.example)
874        )
875
876        a = array.array(self.typecode, self.example)
877        a[:-1000] = a
878        self.assertEqual(
879            a,
880            array.array(self.typecode, 2*self.example)
881        )
882
883        a = array.array(self.typecode, self.example)
884        a[1:0] = a
885        self.assertEqual(
886            a,
887            array.array(self.typecode, self.example[:1] + self.example + self.example[1:])
888        )
889
890        a = array.array(self.typecode, self.example)
891        a[2000:1000] = a
892        self.assertEqual(
893            a,
894            array.array(self.typecode, 2*self.example)
895        )
896
897        a = array.array(self.typecode, self.example)
898        self.assertRaises(TypeError, a.__setitem__, slice(0, 0), None)
899        self.assertRaises(TypeError, a.__setitem__, slice(0, 1), None)
900
901        b = array.array(self.badtypecode())
902        self.assertRaises(TypeError, a.__setitem__, slice(0, 0), b)
903        self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
904
905    def test_extended_set_del_slice(self):
906        indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
907        for start in indices:
908            for stop in indices:
909                # Everything except the initial 0 (invalid step)
910                for step in indices[1:]:
911                    a = array.array(self.typecode, self.example)
912                    L = list(a)
913                    # Make sure we have a slice of exactly the right length,
914                    # but with (hopefully) different data.
915                    data = L[start:stop:step]
916                    data.reverse()
917                    L[start:stop:step] = data
918                    a[start:stop:step] = array.array(self.typecode, data)
919                    self.assertEqual(a, array.array(self.typecode, L))
920
921                    del L[start:stop:step]
922                    del a[start:stop:step]
923                    self.assertEqual(a, array.array(self.typecode, L))
924
925    def test_index(self):
926        example = 2*self.example
927        a = array.array(self.typecode, example)
928        self.assertRaises(TypeError, a.index)
929        for x in example:
930            self.assertEqual(a.index(x), example.index(x))
931        self.assertRaises(ValueError, a.index, None)
932        self.assertRaises(ValueError, a.index, self.outside)
933
934        a = array.array('i', [-2, -1, 0, 0, 1, 2])
935        self.assertEqual(a.index(0), 2)
936        self.assertEqual(a.index(0, 2), 2)
937        self.assertEqual(a.index(0, -4), 2)
938        self.assertEqual(a.index(-2, -10), 0)
939        self.assertEqual(a.index(0, 3), 3)
940        self.assertEqual(a.index(0, -3), 3)
941        self.assertEqual(a.index(0, 3, 4), 3)
942        self.assertEqual(a.index(0, -3, -2), 3)
943        self.assertRaises(ValueError, a.index, 2, 0, -10)
944
945    def test_count(self):
946        example = 2*self.example
947        a = array.array(self.typecode, example)
948        self.assertRaises(TypeError, a.count)
949        for x in example:
950            self.assertEqual(a.count(x), example.count(x))
951        self.assertEqual(a.count(self.outside), 0)
952        self.assertEqual(a.count(None), 0)
953
954    def test_remove(self):
955        for x in self.example:
956            example = 2*self.example
957            a = array.array(self.typecode, example)
958            pos = example.index(x)
959            example2 = example[:pos] + example[pos+1:]
960            a.remove(x)
961            self.assertEqual(a, array.array(self.typecode, example2))
962
963        a = array.array(self.typecode, self.example)
964        self.assertRaises(ValueError, a.remove, self.outside)
965
966        self.assertRaises(ValueError, a.remove, None)
967
968    def test_pop(self):
969        a = array.array(self.typecode)
970        self.assertRaises(IndexError, a.pop)
971
972        a = array.array(self.typecode, 2*self.example)
973        self.assertRaises(TypeError, a.pop, 42, 42)
974        self.assertRaises(TypeError, a.pop, None)
975        self.assertRaises(IndexError, a.pop, len(a))
976        self.assertRaises(IndexError, a.pop, -len(a)-1)
977
978        self.assertEntryEqual(a.pop(0), self.example[0])
979        self.assertEqual(
980            a,
981            array.array(self.typecode, self.example[1:]+self.example)
982        )
983        self.assertEntryEqual(a.pop(1), self.example[2])
984        self.assertEqual(
985            a,
986            array.array(self.typecode, self.example[1:2]+self.example[3:]+self.example)
987        )
988        self.assertEntryEqual(a.pop(0), self.example[1])
989        self.assertEntryEqual(a.pop(), self.example[-1])
990        self.assertEqual(
991            a,
992            array.array(self.typecode, self.example[3:]+self.example[:-1])
993        )
994
995    def test_reverse(self):
996        a = array.array(self.typecode, self.example)
997        self.assertRaises(TypeError, a.reverse, 42)
998        a.reverse()
999        self.assertEqual(
1000            a,
1001            array.array(self.typecode, self.example[::-1])
1002        )
1003
1004    def test_extend(self):
1005        a = array.array(self.typecode, self.example)
1006        self.assertRaises(TypeError, a.extend)
1007        a.extend(array.array(self.typecode, self.example[::-1]))
1008        self.assertEqual(
1009            a,
1010            array.array(self.typecode, self.example+self.example[::-1])
1011        )
1012
1013        a = array.array(self.typecode, self.example)
1014        a.extend(a)
1015        self.assertEqual(
1016            a,
1017            array.array(self.typecode, self.example+self.example)
1018        )
1019
1020        b = array.array(self.badtypecode())
1021        self.assertRaises(TypeError, a.extend, b)
1022
1023        a = array.array(self.typecode, self.example)
1024        a.extend(self.example[::-1])
1025        self.assertEqual(
1026            a,
1027            array.array(self.typecode, self.example+self.example[::-1])
1028        )
1029
1030    def test_constructor_with_iterable_argument(self):
1031        a = array.array(self.typecode, iter(self.example))
1032        b = array.array(self.typecode, self.example)
1033        self.assertEqual(a, b)
1034
1035        # non-iterable argument
1036        self.assertRaises(TypeError, array.array, self.typecode, 10)
1037
1038        # pass through errors raised in __iter__
1039        class A:
1040            def __iter__(self):
1041                raise UnicodeError
1042        self.assertRaises(UnicodeError, array.array, self.typecode, A())
1043
1044        # pass through errors raised in next()
1045        def B():
1046            raise UnicodeError
1047            yield None
1048        self.assertRaises(UnicodeError, array.array, self.typecode, B())
1049
1050    def test_coveritertraverse(self):
1051        try:
1052            import gc
1053        except ImportError:
1054            self.skipTest('gc module not available')
1055        a = array.array(self.typecode)
1056        l = [iter(a)]
1057        l.append(l)
1058        gc.collect()
1059
1060    def test_buffer(self):
1061        a = array.array(self.typecode, self.example)
1062        m = memoryview(a)
1063        expected = m.tobytes()
1064        self.assertEqual(a.tobytes(), expected)
1065        self.assertEqual(a.tobytes()[0], expected[0])
1066        # Resizing is forbidden when there are buffer exports.
1067        # For issue 4509, we also check after each error that
1068        # the array was not modified.
1069        self.assertRaises(BufferError, a.append, a[0])
1070        self.assertEqual(m.tobytes(), expected)
1071        self.assertRaises(BufferError, a.extend, a[0:1])
1072        self.assertEqual(m.tobytes(), expected)
1073        self.assertRaises(BufferError, a.remove, a[0])
1074        self.assertEqual(m.tobytes(), expected)
1075        self.assertRaises(BufferError, a.pop, 0)
1076        self.assertEqual(m.tobytes(), expected)
1077        self.assertRaises(BufferError, a.fromlist, a.tolist())
1078        self.assertEqual(m.tobytes(), expected)
1079        self.assertRaises(BufferError, a.frombytes, a.tobytes())
1080        self.assertEqual(m.tobytes(), expected)
1081        if self.typecode == 'u':
1082            self.assertRaises(BufferError, a.fromunicode, a.tounicode())
1083            self.assertEqual(m.tobytes(), expected)
1084        self.assertRaises(BufferError, operator.imul, a, 2)
1085        self.assertEqual(m.tobytes(), expected)
1086        self.assertRaises(BufferError, operator.imul, a, 0)
1087        self.assertEqual(m.tobytes(), expected)
1088        self.assertRaises(BufferError, operator.setitem, a, slice(0, 0), a)
1089        self.assertEqual(m.tobytes(), expected)
1090        self.assertRaises(BufferError, operator.delitem, a, 0)
1091        self.assertEqual(m.tobytes(), expected)
1092        self.assertRaises(BufferError, operator.delitem, a, slice(0, 1))
1093        self.assertEqual(m.tobytes(), expected)
1094
1095    def test_weakref(self):
1096        s = array.array(self.typecode, self.example)
1097        p = weakref.proxy(s)
1098        self.assertEqual(p.tobytes(), s.tobytes())
1099        s = None
1100        support.gc_collect()  # For PyPy or other GCs.
1101        self.assertRaises(ReferenceError, len, p)
1102
1103    @unittest.skipUnless(hasattr(sys, 'getrefcount'),
1104                         'test needs sys.getrefcount()')
1105    def test_bug_782369(self):
1106        for i in range(10):
1107            b = array.array('B', range(64))
1108        rc = sys.getrefcount(10)
1109        for i in range(10):
1110            b = array.array('B', range(64))
1111        self.assertEqual(rc, sys.getrefcount(10))
1112
1113    def test_subclass_with_kwargs(self):
1114        # SF bug #1486663 -- this used to erroneously raise a TypeError
1115        ArraySubclassWithKwargs('b', newarg=1)
1116
1117    def test_create_from_bytes(self):
1118        # XXX This test probably needs to be moved in a subclass or
1119        # generalized to use self.typecode.
1120        a = array.array('H', b"1234")
1121        self.assertEqual(len(a) * a.itemsize, 4)
1122
1123    @support.cpython_only
1124    def test_sizeof_with_buffer(self):
1125        a = array.array(self.typecode, self.example)
1126        basesize = support.calcvobjsize('Pn2Pi')
1127        buffer_size = a.buffer_info()[1] * a.itemsize
1128        support.check_sizeof(self, a, basesize + buffer_size)
1129
1130    @support.cpython_only
1131    def test_sizeof_without_buffer(self):
1132        a = array.array(self.typecode)
1133        basesize = support.calcvobjsize('Pn2Pi')
1134        support.check_sizeof(self, a, basesize)
1135
1136    def test_initialize_with_unicode(self):
1137        if self.typecode != 'u':
1138            with self.assertRaises(TypeError) as cm:
1139                a = array.array(self.typecode, 'foo')
1140            self.assertIn("cannot use a str", str(cm.exception))
1141            with self.assertRaises(TypeError) as cm:
1142                a = array.array(self.typecode, array.array('u', 'foo'))
1143            self.assertIn("cannot use a unicode array", str(cm.exception))
1144        else:
1145            a = array.array(self.typecode, "foo")
1146            a = array.array(self.typecode, array.array('u', 'foo'))
1147
1148    @support.cpython_only
1149    def test_obsolete_write_lock(self):
1150        from _testcapi import getbuffer_with_null_view
1151        a = array.array('B', b"")
1152        self.assertRaises(BufferError, getbuffer_with_null_view, a)
1153
1154    def test_free_after_iterating(self):
1155        support.check_free_after_iterating(self, iter, array.array,
1156                                           (self.typecode,))
1157        support.check_free_after_iterating(self, reversed, array.array,
1158                                           (self.typecode,))
1159
1160class StringTest(BaseTest):
1161
1162    def test_setitem(self):
1163        super().test_setitem()
1164        a = array.array(self.typecode, self.example)
1165        self.assertRaises(TypeError, a.__setitem__, 0, self.example[:2])
1166
1167class UnicodeTest(StringTest, unittest.TestCase):
1168    typecode = 'u'
1169    example = '\x01\u263a\x00\ufeff'
1170    smallerexample = '\x01\u263a\x00\ufefe'
1171    biggerexample = '\x01\u263a\x01\ufeff'
1172    outside = str('\x33')
1173    minitemsize = 2
1174
1175    def test_unicode(self):
1176        self.assertRaises(TypeError, array.array, 'b', 'foo')
1177
1178        a = array.array('u', '\xa0\xc2\u1234')
1179        a.fromunicode(' ')
1180        a.fromunicode('')
1181        a.fromunicode('')
1182        a.fromunicode('\x11abc\xff\u1234')
1183        s = a.tounicode()
1184        self.assertEqual(s, '\xa0\xc2\u1234 \x11abc\xff\u1234')
1185        self.assertEqual(a.itemsize, sizeof_wchar)
1186
1187        s = '\x00="\'a\\b\x80\xff\u0000\u0001\u1234'
1188        a = array.array('u', s)
1189        self.assertEqual(
1190            repr(a),
1191            "array('u', '\\x00=\"\\'a\\\\b\\x80\xff\\x00\\x01\u1234')")
1192
1193        self.assertRaises(TypeError, a.fromunicode)
1194
1195    def test_issue17223(self):
1196        # this used to crash
1197        if sizeof_wchar == 4:
1198            # U+FFFFFFFF is an invalid code point in Unicode 6.0
1199            invalid_str = b'\xff\xff\xff\xff'
1200        else:
1201            # PyUnicode_FromUnicode() cannot fail with 16-bit wchar_t
1202            self.skipTest("specific to 32-bit wchar_t")
1203        a = array.array('u', invalid_str)
1204        self.assertRaises(ValueError, a.tounicode)
1205        self.assertRaises(ValueError, str, a)
1206
1207class NumberTest(BaseTest):
1208
1209    def test_extslice(self):
1210        a = array.array(self.typecode, range(5))
1211        self.assertEqual(a[::], a)
1212        self.assertEqual(a[::2], array.array(self.typecode, [0,2,4]))
1213        self.assertEqual(a[1::2], array.array(self.typecode, [1,3]))
1214        self.assertEqual(a[::-1], array.array(self.typecode, [4,3,2,1,0]))
1215        self.assertEqual(a[::-2], array.array(self.typecode, [4,2,0]))
1216        self.assertEqual(a[3::-2], array.array(self.typecode, [3,1]))
1217        self.assertEqual(a[-100:100:], a)
1218        self.assertEqual(a[100:-100:-1], a[::-1])
1219        self.assertEqual(a[-100:100:2], array.array(self.typecode, [0,2,4]))
1220        self.assertEqual(a[1000:2000:2], array.array(self.typecode, []))
1221        self.assertEqual(a[-1000:-2000:-2], array.array(self.typecode, []))
1222
1223    def test_delslice(self):
1224        a = array.array(self.typecode, range(5))
1225        del a[::2]
1226        self.assertEqual(a, array.array(self.typecode, [1,3]))
1227        a = array.array(self.typecode, range(5))
1228        del a[1::2]
1229        self.assertEqual(a, array.array(self.typecode, [0,2,4]))
1230        a = array.array(self.typecode, range(5))
1231        del a[1::-2]
1232        self.assertEqual(a, array.array(self.typecode, [0,2,3,4]))
1233        a = array.array(self.typecode, range(10))
1234        del a[::1000]
1235        self.assertEqual(a, array.array(self.typecode, [1,2,3,4,5,6,7,8,9]))
1236        # test issue7788
1237        a = array.array(self.typecode, range(10))
1238        del a[9::1<<333]
1239
1240    def test_assignment(self):
1241        a = array.array(self.typecode, range(10))
1242        a[::2] = array.array(self.typecode, [42]*5)
1243        self.assertEqual(a, array.array(self.typecode, [42, 1, 42, 3, 42, 5, 42, 7, 42, 9]))
1244        a = array.array(self.typecode, range(10))
1245        a[::-4] = array.array(self.typecode, [10]*3)
1246        self.assertEqual(a, array.array(self.typecode, [0, 10, 2, 3, 4, 10, 6, 7, 8 ,10]))
1247        a = array.array(self.typecode, range(4))
1248        a[::-1] = a
1249        self.assertEqual(a, array.array(self.typecode, [3, 2, 1, 0]))
1250        a = array.array(self.typecode, range(10))
1251        b = a[:]
1252        c = a[:]
1253        ins = array.array(self.typecode, range(2))
1254        a[2:3] = ins
1255        b[slice(2,3)] = ins
1256        c[2:3:] = ins
1257
1258    def test_iterationcontains(self):
1259        a = array.array(self.typecode, range(10))
1260        self.assertEqual(list(a), list(range(10)))
1261        b = array.array(self.typecode, [20])
1262        self.assertEqual(a[-1] in a, True)
1263        self.assertEqual(b[0] not in a, True)
1264
1265    def check_overflow(self, lower, upper):
1266        # method to be used by subclasses
1267
1268        # should not overflow assigning lower limit
1269        a = array.array(self.typecode, [lower])
1270        a[0] = lower
1271        # should overflow assigning less than lower limit
1272        self.assertRaises(OverflowError, array.array, self.typecode, [lower-1])
1273        self.assertRaises(OverflowError, a.__setitem__, 0, lower-1)
1274        # should not overflow assigning upper limit
1275        a = array.array(self.typecode, [upper])
1276        a[0] = upper
1277        # should overflow assigning more than upper limit
1278        self.assertRaises(OverflowError, array.array, self.typecode, [upper+1])
1279        self.assertRaises(OverflowError, a.__setitem__, 0, upper+1)
1280
1281    def test_subclassing(self):
1282        typecode = self.typecode
1283        class ExaggeratingArray(array.array):
1284            __slots__ = ['offset']
1285
1286            def __new__(cls, typecode, data, offset):
1287                return array.array.__new__(cls, typecode, data)
1288
1289            def __init__(self, typecode, data, offset):
1290                self.offset = offset
1291
1292            def __getitem__(self, i):
1293                return array.array.__getitem__(self, i) + self.offset
1294
1295        a = ExaggeratingArray(self.typecode, [3, 6, 7, 11], 4)
1296        self.assertEntryEqual(a[0], 7)
1297
1298        self.assertRaises(AttributeError, setattr, a, "color", "blue")
1299
1300    def test_frombytearray(self):
1301        a = array.array('b', range(10))
1302        b = array.array(self.typecode, a)
1303        self.assertEqual(a, b)
1304
1305class IntegerNumberTest(NumberTest):
1306    def test_type_error(self):
1307        a = array.array(self.typecode)
1308        a.append(42)
1309        with self.assertRaises(TypeError):
1310            a.append(42.0)
1311        with self.assertRaises(TypeError):
1312            a[0] = 42.0
1313
1314class Intable:
1315    def __init__(self, num):
1316        self._num = num
1317    def __index__(self):
1318        return self._num
1319    def __int__(self):
1320        return self._num
1321    def __sub__(self, other):
1322        return Intable(int(self) - int(other))
1323    def __add__(self, other):
1324        return Intable(int(self) + int(other))
1325
1326class SignedNumberTest(IntegerNumberTest):
1327    example = [-1, 0, 1, 42, 0x7f]
1328    smallerexample = [-1, 0, 1, 42, 0x7e]
1329    biggerexample = [-1, 0, 1, 43, 0x7f]
1330    outside = 23
1331
1332    def test_overflow(self):
1333        a = array.array(self.typecode)
1334        lower = -1 * int(pow(2, a.itemsize * 8 - 1))
1335        upper = int(pow(2, a.itemsize * 8 - 1)) - 1
1336        self.check_overflow(lower, upper)
1337        self.check_overflow(Intable(lower), Intable(upper))
1338
1339class UnsignedNumberTest(IntegerNumberTest):
1340    example = [0, 1, 17, 23, 42, 0xff]
1341    smallerexample = [0, 1, 17, 23, 42, 0xfe]
1342    biggerexample = [0, 1, 17, 23, 43, 0xff]
1343    outside = 0xaa
1344
1345    def test_overflow(self):
1346        a = array.array(self.typecode)
1347        lower = 0
1348        upper = int(pow(2, a.itemsize * 8)) - 1
1349        self.check_overflow(lower, upper)
1350        self.check_overflow(Intable(lower), Intable(upper))
1351
1352    def test_bytes_extend(self):
1353        s = bytes(self.example)
1354
1355        a = array.array(self.typecode, self.example)
1356        a.extend(s)
1357        self.assertEqual(
1358            a,
1359            array.array(self.typecode, self.example+self.example)
1360        )
1361
1362        a = array.array(self.typecode, self.example)
1363        a.extend(bytearray(reversed(s)))
1364        self.assertEqual(
1365            a,
1366            array.array(self.typecode, self.example+self.example[::-1])
1367        )
1368
1369
1370class ByteTest(SignedNumberTest, unittest.TestCase):
1371    typecode = 'b'
1372    minitemsize = 1
1373
1374class UnsignedByteTest(UnsignedNumberTest, unittest.TestCase):
1375    typecode = 'B'
1376    minitemsize = 1
1377
1378class ShortTest(SignedNumberTest, unittest.TestCase):
1379    typecode = 'h'
1380    minitemsize = 2
1381
1382class UnsignedShortTest(UnsignedNumberTest, unittest.TestCase):
1383    typecode = 'H'
1384    minitemsize = 2
1385
1386class IntTest(SignedNumberTest, unittest.TestCase):
1387    typecode = 'i'
1388    minitemsize = 2
1389
1390class UnsignedIntTest(UnsignedNumberTest, unittest.TestCase):
1391    typecode = 'I'
1392    minitemsize = 2
1393
1394class LongTest(SignedNumberTest, unittest.TestCase):
1395    typecode = 'l'
1396    minitemsize = 4
1397
1398class UnsignedLongTest(UnsignedNumberTest, unittest.TestCase):
1399    typecode = 'L'
1400    minitemsize = 4
1401
1402class LongLongTest(SignedNumberTest, unittest.TestCase):
1403    typecode = 'q'
1404    minitemsize = 8
1405
1406class UnsignedLongLongTest(UnsignedNumberTest, unittest.TestCase):
1407    typecode = 'Q'
1408    minitemsize = 8
1409
1410class FPTest(NumberTest):
1411    example = [-42.0, 0, 42, 1e5, -1e10]
1412    smallerexample = [-42.0, 0, 42, 1e5, -2e10]
1413    biggerexample = [-42.0, 0, 42, 1e5, 1e10]
1414    outside = 23
1415
1416    def assertEntryEqual(self, entry1, entry2):
1417        self.assertAlmostEqual(entry1, entry2)
1418
1419    def test_nan(self):
1420        a = array.array(self.typecode, [float('nan')])
1421        b = array.array(self.typecode, [float('nan')])
1422        self.assertIs(a != b, True)
1423        self.assertIs(a == b, False)
1424        self.assertIs(a > b, False)
1425        self.assertIs(a >= b, False)
1426        self.assertIs(a < b, False)
1427        self.assertIs(a <= b, False)
1428
1429    def test_byteswap(self):
1430        a = array.array(self.typecode, self.example)
1431        self.assertRaises(TypeError, a.byteswap, 42)
1432        if a.itemsize in (1, 2, 4, 8):
1433            b = array.array(self.typecode, self.example)
1434            b.byteswap()
1435            if a.itemsize==1:
1436                self.assertEqual(a, b)
1437            else:
1438                # On alphas treating the byte swapped bit patters as
1439                # floats/doubles results in floating point exceptions
1440                # => compare the 8bit string values instead
1441                self.assertNotEqual(a.tobytes(), b.tobytes())
1442            b.byteswap()
1443            self.assertEqual(a, b)
1444
1445class FloatTest(FPTest, unittest.TestCase):
1446    typecode = 'f'
1447    minitemsize = 4
1448
1449class DoubleTest(FPTest, unittest.TestCase):
1450    typecode = 'd'
1451    minitemsize = 8
1452
1453    def test_alloc_overflow(self):
1454        from sys import maxsize
1455        a = array.array('d', [-1]*65536)
1456        try:
1457            a *= maxsize//65536 + 1
1458        except MemoryError:
1459            pass
1460        else:
1461            self.fail("Array of size > maxsize created - MemoryError expected")
1462        b = array.array('d', [ 2.71828183, 3.14159265, -1])
1463        try:
1464            b * (maxsize//3 + 1)
1465        except MemoryError:
1466            pass
1467        else:
1468            self.fail("Array of size > maxsize created - MemoryError expected")
1469
1470
1471class LargeArrayTest(unittest.TestCase):
1472    typecode = 'b'
1473
1474    def example(self, size):
1475        # We assess a base memuse of <=2.125 for constructing this array
1476        base = array.array(self.typecode, [0, 1, 2, 3, 4, 5, 6, 7]) * (size // 8)
1477        base += array.array(self.typecode, [99]*(size % 8) + [8, 9, 10, 11])
1478        return base
1479
1480    @support.bigmemtest(_2G, memuse=2.125)
1481    def test_example_data(self, size):
1482        example = self.example(size)
1483        self.assertEqual(len(example), size+4)
1484
1485    @support.bigmemtest(_2G, memuse=2.125)
1486    def test_access(self, size):
1487        example = self.example(size)
1488        self.assertEqual(example[0], 0)
1489        self.assertEqual(example[-(size+4)], 0)
1490        self.assertEqual(example[size], 8)
1491        self.assertEqual(example[-4], 8)
1492        self.assertEqual(example[size+3], 11)
1493        self.assertEqual(example[-1], 11)
1494
1495    @support.bigmemtest(_2G, memuse=2.125+1)
1496    def test_slice(self, size):
1497        example = self.example(size)
1498        self.assertEqual(list(example[:4]), [0, 1, 2, 3])
1499        self.assertEqual(list(example[-4:]), [8, 9, 10, 11])
1500        part = example[1:-1]
1501        self.assertEqual(len(part), size+2)
1502        self.assertEqual(part[0], 1)
1503        self.assertEqual(part[-1], 10)
1504        del part
1505        part = example[::2]
1506        self.assertEqual(len(part), (size+5)//2)
1507        self.assertEqual(list(part[:4]), [0, 2, 4, 6])
1508        if size % 2:
1509            self.assertEqual(list(part[-2:]), [9, 11])
1510        else:
1511            self.assertEqual(list(part[-2:]), [8, 10])
1512
1513    @support.bigmemtest(_2G, memuse=2.125)
1514    def test_count(self, size):
1515        example = self.example(size)
1516        self.assertEqual(example.count(0), size//8)
1517        self.assertEqual(example.count(11), 1)
1518
1519    @support.bigmemtest(_2G, memuse=2.125)
1520    def test_append(self, size):
1521        example = self.example(size)
1522        example.append(12)
1523        self.assertEqual(example[-1], 12)
1524
1525    @support.bigmemtest(_2G, memuse=2.125)
1526    def test_extend(self, size):
1527        example = self.example(size)
1528        example.extend(iter([12, 13, 14, 15]))
1529        self.assertEqual(len(example), size+8)
1530        self.assertEqual(list(example[-8:]), [8, 9, 10, 11, 12, 13, 14, 15])
1531
1532    @support.bigmemtest(_2G, memuse=2.125)
1533    def test_frombytes(self, size):
1534        example = self.example(size)
1535        example.frombytes(b'abcd')
1536        self.assertEqual(len(example), size+8)
1537        self.assertEqual(list(example[-8:]), [8, 9, 10, 11] + list(b'abcd'))
1538
1539    @support.bigmemtest(_2G, memuse=2.125)
1540    def test_fromlist(self, size):
1541        example = self.example(size)
1542        example.fromlist([12, 13, 14, 15])
1543        self.assertEqual(len(example), size+8)
1544        self.assertEqual(list(example[-8:]), [8, 9, 10, 11, 12, 13, 14, 15])
1545
1546    @support.bigmemtest(_2G, memuse=2.125)
1547    def test_index(self, size):
1548        example = self.example(size)
1549        self.assertEqual(example.index(0), 0)
1550        self.assertEqual(example.index(1), 1)
1551        self.assertEqual(example.index(7), 7)
1552        self.assertEqual(example.index(11), size+3)
1553
1554    @support.bigmemtest(_2G, memuse=2.125)
1555    def test_insert(self, size):
1556        example = self.example(size)
1557        example.insert(0, 12)
1558        example.insert(10, 13)
1559        example.insert(size+1, 14)
1560        self.assertEqual(len(example), size+7)
1561        self.assertEqual(example[0], 12)
1562        self.assertEqual(example[10], 13)
1563        self.assertEqual(example[size+1], 14)
1564
1565    @support.bigmemtest(_2G, memuse=2.125)
1566    def test_pop(self, size):
1567        example = self.example(size)
1568        self.assertEqual(example.pop(0), 0)
1569        self.assertEqual(example[0], 1)
1570        self.assertEqual(example.pop(size+1), 10)
1571        self.assertEqual(example[size+1], 11)
1572        self.assertEqual(example.pop(1), 2)
1573        self.assertEqual(example[1], 3)
1574        self.assertEqual(len(example), size+1)
1575        self.assertEqual(example.pop(), 11)
1576        self.assertEqual(len(example), size)
1577
1578    @support.bigmemtest(_2G, memuse=2.125)
1579    def test_remove(self, size):
1580        example = self.example(size)
1581        example.remove(0)
1582        self.assertEqual(len(example), size+3)
1583        self.assertEqual(example[0], 1)
1584        example.remove(10)
1585        self.assertEqual(len(example), size+2)
1586        self.assertEqual(example[size], 9)
1587        self.assertEqual(example[size+1], 11)
1588
1589    @support.bigmemtest(_2G, memuse=2.125)
1590    def test_reverse(self, size):
1591        example = self.example(size)
1592        example.reverse()
1593        self.assertEqual(len(example), size+4)
1594        self.assertEqual(example[0], 11)
1595        self.assertEqual(example[3], 8)
1596        self.assertEqual(example[-1], 0)
1597        example.reverse()
1598        self.assertEqual(len(example), size+4)
1599        self.assertEqual(list(example[:4]), [0, 1, 2, 3])
1600        self.assertEqual(list(example[-4:]), [8, 9, 10, 11])
1601
1602    # list takes about 9 bytes per element
1603    @support.bigmemtest(_2G, memuse=2.125+9)
1604    def test_tolist(self, size):
1605        example = self.example(size)
1606        ls = example.tolist()
1607        self.assertEqual(len(ls), len(example))
1608        self.assertEqual(ls[:8], list(example[:8]))
1609        self.assertEqual(ls[-8:], list(example[-8:]))
1610
1611if __name__ == "__main__":
1612    unittest.main()
1613