1"""Test the arraymodule.
2   Roger E. Masse
3"""
4
5import unittest
6import warnings
7from test import test_support
8from weakref import proxy
9import array, cStringIO
10from cPickle import loads, dumps, HIGHEST_PROTOCOL
11import sys
12
13class ArraySubclass(array.array):
14    pass
15
16class ArraySubclassWithKwargs(array.array):
17    def __init__(self, typecode, newarg=None):
18        array.array.__init__(self, typecode)
19
20tests = [] # list to accumulate all tests
21typecodes = "cbBhHiIlLfd"
22if test_support.have_unicode:
23    typecodes += "u"
24
25class MiscTest(unittest.TestCase):
26
27    def test_bad_constructor(self):
28        self.assertRaises(TypeError, array.array)
29        self.assertRaises(TypeError, array.array, spam=42)
30        self.assertRaises(TypeError, array.array, 'xx')
31        self.assertRaises(TypeError, array.array, '')
32        self.assertRaises(TypeError, array.array, 1)
33        self.assertRaises(ValueError, array.array, 'x')
34        self.assertRaises(ValueError, array.array, '\x80')
35
36    @test_support.requires_unicode
37    def test_unicode_constructor(self):
38        self.assertRaises(TypeError, array.array, u'xx')
39        self.assertRaises(TypeError, array.array, u'')
40        self.assertRaises(ValueError, array.array, u'x')
41        self.assertRaises(ValueError, array.array, u'\x80')
42
43    def test_empty(self):
44        # Exercise code for handling zero-length arrays
45        a = array.array('B')
46        a[:] = a
47        self.assertEqual(len(a), 0)
48        self.assertEqual(len(a + a), 0)
49        self.assertEqual(len(a * 3), 0)
50        a += a
51        self.assertEqual(len(a), 0)
52
53tests.append(MiscTest)
54
55class BaseTest(unittest.TestCase):
56    # Required class attributes (provided by subclasses
57    # typecode: the typecode to test
58    # example: an initializer usable in the constructor for this type
59    # smallerexample: the same length as example, but smaller
60    # biggerexample: the same length as example, but bigger
61    # outside: An entry that is not in example
62    # minitemsize: the minimum guaranteed itemsize
63
64    def assertEntryEqual(self, entry1, entry2):
65        self.assertEqual(entry1, entry2)
66
67    def badtypecode(self):
68        # Return a typecode that is different from our own
69        return typecodes[(typecodes.index(self.typecode)+1) % len(typecodes)]
70
71    def test_constructor(self):
72        a = array.array(self.typecode)
73        self.assertEqual(a.typecode, self.typecode)
74        self.assertGreaterEqual(a.itemsize, self.minitemsize)
75        self.assertRaises(TypeError, array.array, self.typecode, None)
76
77    def test_len(self):
78        a = array.array(self.typecode)
79        a.append(self.example[0])
80        self.assertEqual(len(a), 1)
81
82        a = array.array(self.typecode, self.example)
83        self.assertEqual(len(a), len(self.example))
84
85    def test_buffer_info(self):
86        a = array.array(self.typecode, self.example)
87        self.assertRaises(TypeError, a.buffer_info, 42)
88        bi = a.buffer_info()
89        self.assertIsInstance(bi, tuple)
90        self.assertEqual(len(bi), 2)
91        self.assertIsInstance(bi[0], (int, long))
92        self.assertIsInstance(bi[1], int)
93        self.assertEqual(bi[1], len(a))
94
95    def test_byteswap(self):
96        a = array.array(self.typecode, self.example)
97        self.assertRaises(TypeError, a.byteswap, 42)
98        if a.itemsize in (1, 2, 4, 8):
99            b = array.array(self.typecode, self.example)
100            b.byteswap()
101            if a.itemsize==1:
102                self.assertEqual(a, b)
103            else:
104                self.assertNotEqual(a, b)
105            b.byteswap()
106            self.assertEqual(a, b)
107
108    def test_copy(self):
109        import copy
110        a = array.array(self.typecode, self.example)
111        b = copy.copy(a)
112        self.assertNotEqual(id(a), id(b))
113        self.assertEqual(a, b)
114
115    def test_deepcopy(self):
116        import copy
117        a = array.array(self.typecode, self.example)
118        b = copy.deepcopy(a)
119        self.assertNotEqual(id(a), id(b))
120        self.assertEqual(a, b)
121
122    def test_pickle(self):
123        for protocol in range(HIGHEST_PROTOCOL + 1):
124            a = array.array(self.typecode, self.example)
125            b = loads(dumps(a, protocol))
126            self.assertNotEqual(id(a), id(b))
127            self.assertEqual(a, b)
128
129            a = ArraySubclass(self.typecode, self.example)
130            a.x = 10
131            b = loads(dumps(a, protocol))
132            self.assertNotEqual(id(a), id(b))
133            self.assertEqual(a, b)
134            self.assertEqual(a.x, b.x)
135            self.assertEqual(type(a), type(b))
136
137    def test_pickle_for_empty_array(self):
138        for protocol in range(HIGHEST_PROTOCOL + 1):
139            a = array.array(self.typecode)
140            b = loads(dumps(a, protocol))
141            self.assertNotEqual(id(a), id(b))
142            self.assertEqual(a, b)
143
144            a = ArraySubclass(self.typecode)
145            a.x = 10
146            b = loads(dumps(a, protocol))
147            self.assertNotEqual(id(a), id(b))
148            self.assertEqual(a, b)
149            self.assertEqual(a.x, b.x)
150            self.assertEqual(type(a), type(b))
151
152    def test_insert(self):
153        a = array.array(self.typecode, self.example)
154        a.insert(0, self.example[0])
155        self.assertEqual(len(a), 1+len(self.example))
156        self.assertEqual(a[0], a[1])
157        self.assertRaises(TypeError, a.insert)
158        self.assertRaises(TypeError, a.insert, None)
159        self.assertRaises(TypeError, a.insert, 0, None)
160
161        a = array.array(self.typecode, self.example)
162        a.insert(-1, self.example[0])
163        self.assertEqual(
164            a,
165            array.array(
166                self.typecode,
167                self.example[:-1] + self.example[:1] + self.example[-1:]
168            )
169        )
170
171        a = array.array(self.typecode, self.example)
172        a.insert(-1000, self.example[0])
173        self.assertEqual(
174            a,
175            array.array(self.typecode, self.example[:1] + self.example)
176        )
177
178        a = array.array(self.typecode, self.example)
179        a.insert(1000, self.example[0])
180        self.assertEqual(
181            a,
182            array.array(self.typecode, self.example + self.example[:1])
183        )
184
185    def test_tofromfile(self):
186        a = array.array(self.typecode, 2*self.example)
187        self.assertRaises(TypeError, a.tofile)
188        self.assertRaises(TypeError, a.tofile, cStringIO.StringIO())
189        test_support.unlink(test_support.TESTFN)
190        f = open(test_support.TESTFN, 'wb')
191        try:
192            a.tofile(f)
193            f.close()
194            b = array.array(self.typecode)
195            f = open(test_support.TESTFN, 'rb')
196            self.assertRaises(TypeError, b.fromfile)
197            self.assertRaises(
198                TypeError,
199                b.fromfile,
200                cStringIO.StringIO(), len(self.example)
201            )
202            b.fromfile(f, len(self.example))
203            self.assertEqual(b, array.array(self.typecode, self.example))
204            self.assertNotEqual(a, b)
205            b.fromfile(f, len(self.example))
206            self.assertEqual(a, b)
207            self.assertRaises(EOFError, b.fromfile, f, 1)
208            f.close()
209        finally:
210            if not f.closed:
211                f.close()
212            test_support.unlink(test_support.TESTFN)
213
214    def test_fromfile_ioerror(self):
215        # Issue #5395: Check if fromfile raises a proper IOError
216        # instead of EOFError.
217        a = array.array(self.typecode)
218        f = open(test_support.TESTFN, 'wb')
219        try:
220            self.assertRaises(IOError, a.fromfile, f, len(self.example))
221        finally:
222            f.close()
223            test_support.unlink(test_support.TESTFN)
224
225    def test_filewrite(self):
226        a = array.array(self.typecode, 2*self.example)
227        f = open(test_support.TESTFN, 'wb')
228        try:
229            f.write(a)
230            f.close()
231            b = array.array(self.typecode)
232            f = open(test_support.TESTFN, 'rb')
233            b.fromfile(f, len(self.example))
234            self.assertEqual(b, array.array(self.typecode, self.example))
235            self.assertNotEqual(a, b)
236            b.fromfile(f, len(self.example))
237            self.assertEqual(a, b)
238            f.close()
239        finally:
240            if not f.closed:
241                f.close()
242            test_support.unlink(test_support.TESTFN)
243
244    def test_tofromlist(self):
245        a = array.array(self.typecode, 2*self.example)
246        b = array.array(self.typecode)
247        self.assertRaises(TypeError, a.tolist, 42)
248        self.assertRaises(TypeError, b.fromlist)
249        self.assertRaises(TypeError, b.fromlist, 42)
250        self.assertRaises(TypeError, b.fromlist, [None])
251        b.fromlist(a.tolist())
252        self.assertEqual(a, b)
253
254    def test_tofromstring(self):
255        a = array.array(self.typecode, 2*self.example)
256        b = array.array(self.typecode)
257        self.assertRaises(TypeError, a.tostring, 42)
258        self.assertRaises(TypeError, b.fromstring)
259        self.assertRaises(TypeError, b.fromstring, 42)
260        self.assertRaises(ValueError, a.fromstring, a)
261        b.fromstring(a.tostring())
262        self.assertEqual(a, b)
263        if a.itemsize>1:
264            self.assertRaises(ValueError, b.fromstring, "x")
265
266    def test_repr(self):
267        a = array.array(self.typecode, 2*self.example)
268        self.assertEqual(a, eval(repr(a), {"array": array.array}))
269
270        a = array.array(self.typecode)
271        self.assertEqual(repr(a), "array('%s')" % self.typecode)
272
273    def test_str(self):
274        a = array.array(self.typecode, 2*self.example)
275        str(a)
276
277    def test_cmp(self):
278        a = array.array(self.typecode, self.example)
279        self.assertIs(a == 42, False)
280        self.assertIs(a != 42, True)
281
282        self.assertIs(a == a, True)
283        self.assertIs(a != a, False)
284        self.assertIs(a < a, False)
285        self.assertIs(a <= a, True)
286        self.assertIs(a > a, False)
287        self.assertIs(a >= a, True)
288
289        al = array.array(self.typecode, self.smallerexample)
290        ab = array.array(self.typecode, self.biggerexample)
291
292        self.assertIs(a == 2*a, False)
293        self.assertIs(a != 2*a, True)
294        self.assertIs(a < 2*a, True)
295        self.assertIs(a <= 2*a, True)
296        self.assertIs(a > 2*a, False)
297        self.assertIs(a >= 2*a, False)
298
299        self.assertIs(a == al, False)
300        self.assertIs(a != al, True)
301        self.assertIs(a < al, False)
302        self.assertIs(a <= al, False)
303        self.assertIs(a > al, True)
304        self.assertIs(a >= al, True)
305
306        self.assertIs(a == ab, False)
307        self.assertIs(a != ab, True)
308        self.assertIs(a < ab, True)
309        self.assertIs(a <= ab, True)
310        self.assertIs(a > ab, False)
311        self.assertIs(a >= ab, False)
312
313    def test_add(self):
314        a = array.array(self.typecode, self.example) \
315            + array.array(self.typecode, self.example[::-1])
316        self.assertEqual(
317            a,
318            array.array(self.typecode, self.example + self.example[::-1])
319        )
320
321        b = array.array(self.badtypecode())
322        self.assertRaises(TypeError, a.__add__, b)
323
324        self.assertRaises(TypeError, a.__add__, "bad")
325
326    def test_iadd(self):
327        a = array.array(self.typecode, self.example[::-1])
328        b = a
329        a += array.array(self.typecode, 2*self.example)
330        self.assertIs(a, b)
331        self.assertEqual(
332            a,
333            array.array(self.typecode, self.example[::-1]+2*self.example)
334        )
335        a = array.array(self.typecode, self.example)
336        a += a
337        self.assertEqual(
338            a,
339            array.array(self.typecode, self.example + self.example)
340        )
341
342        b = array.array(self.badtypecode())
343        self.assertRaises(TypeError, a.__add__, b)
344
345        self.assertRaises(TypeError, a.__iadd__, "bad")
346
347    def test_mul(self):
348        a = 5*array.array(self.typecode, self.example)
349        self.assertEqual(
350            a,
351            array.array(self.typecode, 5*self.example)
352        )
353
354        a = array.array(self.typecode, self.example)*5
355        self.assertEqual(
356            a,
357            array.array(self.typecode, self.example*5)
358        )
359
360        a = 0*array.array(self.typecode, self.example)
361        self.assertEqual(
362            a,
363            array.array(self.typecode)
364        )
365
366        a = (-1)*array.array(self.typecode, self.example)
367        self.assertEqual(
368            a,
369            array.array(self.typecode)
370        )
371
372        self.assertRaises(TypeError, a.__mul__, "bad")
373
374    def test_imul(self):
375        a = array.array(self.typecode, self.example)
376        b = a
377
378        a *= 5
379        self.assertIs(a, b)
380        self.assertEqual(
381            a,
382            array.array(self.typecode, 5*self.example)
383        )
384
385        a *= 0
386        self.assertIs(a, b)
387        self.assertEqual(a, array.array(self.typecode))
388
389        a *= 1000
390        self.assertIs(a, b)
391        self.assertEqual(a, array.array(self.typecode))
392
393        a *= -1
394        self.assertIs(a, b)
395        self.assertEqual(a, array.array(self.typecode))
396
397        a = array.array(self.typecode, self.example)
398        a *= -1
399        self.assertEqual(a, array.array(self.typecode))
400
401        self.assertRaises(TypeError, a.__imul__, "bad")
402
403    def test_getitem(self):
404        a = array.array(self.typecode, self.example)
405        self.assertEntryEqual(a[0], self.example[0])
406        self.assertEntryEqual(a[0L], self.example[0])
407        self.assertEntryEqual(a[-1], self.example[-1])
408        self.assertEntryEqual(a[-1L], self.example[-1])
409        self.assertEntryEqual(a[len(self.example)-1], self.example[-1])
410        self.assertEntryEqual(a[-len(self.example)], self.example[0])
411        self.assertRaises(TypeError, a.__getitem__)
412        self.assertRaises(IndexError, a.__getitem__, len(self.example))
413        self.assertRaises(IndexError, a.__getitem__, -len(self.example)-1)
414
415    def test_setitem(self):
416        a = array.array(self.typecode, self.example)
417        a[0] = a[-1]
418        self.assertEntryEqual(a[0], a[-1])
419
420        a = array.array(self.typecode, self.example)
421        a[0L] = a[-1]
422        self.assertEntryEqual(a[0], a[-1])
423
424        a = array.array(self.typecode, self.example)
425        a[-1] = a[0]
426        self.assertEntryEqual(a[0], a[-1])
427
428        a = array.array(self.typecode, self.example)
429        a[-1L] = a[0]
430        self.assertEntryEqual(a[0], a[-1])
431
432        a = array.array(self.typecode, self.example)
433        a[len(self.example)-1] = a[0]
434        self.assertEntryEqual(a[0], a[-1])
435
436        a = array.array(self.typecode, self.example)
437        a[-len(self.example)] = a[-1]
438        self.assertEntryEqual(a[0], a[-1])
439
440        self.assertRaises(TypeError, a.__setitem__)
441        self.assertRaises(TypeError, a.__setitem__, None)
442        self.assertRaises(TypeError, a.__setitem__, 0, None)
443        self.assertRaises(
444            IndexError,
445            a.__setitem__,
446            len(self.example), self.example[0]
447        )
448        self.assertRaises(
449            IndexError,
450            a.__setitem__,
451            -len(self.example)-1, self.example[0]
452        )
453
454    def test_delitem(self):
455        a = array.array(self.typecode, self.example)
456        del a[0]
457        self.assertEqual(
458            a,
459            array.array(self.typecode, self.example[1:])
460        )
461
462        a = array.array(self.typecode, self.example)
463        del a[-1]
464        self.assertEqual(
465            a,
466            array.array(self.typecode, self.example[:-1])
467        )
468
469        a = array.array(self.typecode, self.example)
470        del a[len(self.example)-1]
471        self.assertEqual(
472            a,
473            array.array(self.typecode, self.example[:-1])
474        )
475
476        a = array.array(self.typecode, self.example)
477        del a[-len(self.example)]
478        self.assertEqual(
479            a,
480            array.array(self.typecode, self.example[1:])
481        )
482
483        self.assertRaises(TypeError, a.__delitem__)
484        self.assertRaises(TypeError, a.__delitem__, None)
485        self.assertRaises(IndexError, a.__delitem__, len(self.example))
486        self.assertRaises(IndexError, a.__delitem__, -len(self.example)-1)
487
488    def test_getslice(self):
489        a = array.array(self.typecode, self.example)
490        self.assertEqual(a[:], a)
491
492        self.assertEqual(
493            a[1:],
494            array.array(self.typecode, self.example[1:])
495        )
496
497        self.assertEqual(
498            a[:1],
499            array.array(self.typecode, self.example[:1])
500        )
501
502        self.assertEqual(
503            a[:-1],
504            array.array(self.typecode, self.example[:-1])
505        )
506
507        self.assertEqual(
508            a[-1:],
509            array.array(self.typecode, self.example[-1:])
510        )
511
512        self.assertEqual(
513            a[-1:-1],
514            array.array(self.typecode)
515        )
516
517        self.assertEqual(
518            a[2:1],
519            array.array(self.typecode)
520        )
521
522        self.assertEqual(
523            a[1000:],
524            array.array(self.typecode)
525        )
526        self.assertEqual(a[-1000:], a)
527        self.assertEqual(a[:1000], a)
528        self.assertEqual(
529            a[:-1000],
530            array.array(self.typecode)
531        )
532        self.assertEqual(a[-1000:1000], a)
533        self.assertEqual(
534            a[2000:1000],
535            array.array(self.typecode)
536        )
537
538    def test_extended_getslice(self):
539        # Test extended slicing by comparing with list slicing
540        # (Assumes list conversion works correctly, too)
541        a = array.array(self.typecode, self.example)
542        indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
543        for start in indices:
544            for stop in indices:
545                # Everything except the initial 0 (invalid step)
546                for step in indices[1:]:
547                    self.assertEqual(list(a[start:stop:step]),
548                                     list(a)[start:stop:step])
549
550    def test_setslice(self):
551        a = array.array(self.typecode, self.example)
552        a[:1] = a
553        self.assertEqual(
554            a,
555            array.array(self.typecode, self.example + self.example[1:])
556        )
557
558        a = array.array(self.typecode, self.example)
559        a[:-1] = a
560        self.assertEqual(
561            a,
562            array.array(self.typecode, self.example + self.example[-1:])
563        )
564
565        a = array.array(self.typecode, self.example)
566        a[-1:] = a
567        self.assertEqual(
568            a,
569            array.array(self.typecode, self.example[:-1] + self.example)
570        )
571
572        a = array.array(self.typecode, self.example)
573        a[1:] = a
574        self.assertEqual(
575            a,
576            array.array(self.typecode, self.example[:1] + self.example)
577        )
578
579        a = array.array(self.typecode, self.example)
580        a[1:-1] = a
581        self.assertEqual(
582            a,
583            array.array(
584                self.typecode,
585                self.example[:1] + self.example + self.example[-1:]
586            )
587        )
588
589        a = array.array(self.typecode, self.example)
590        a[1000:] = a
591        self.assertEqual(
592            a,
593            array.array(self.typecode, 2*self.example)
594        )
595
596        a = array.array(self.typecode, self.example)
597        a[-1000:] = a
598        self.assertEqual(
599            a,
600            array.array(self.typecode, self.example)
601        )
602
603        a = array.array(self.typecode, self.example)
604        a[:1000] = a
605        self.assertEqual(
606            a,
607            array.array(self.typecode, self.example)
608        )
609
610        a = array.array(self.typecode, self.example)
611        a[:-1000] = a
612        self.assertEqual(
613            a,
614            array.array(self.typecode, 2*self.example)
615        )
616
617        a = array.array(self.typecode, self.example)
618        a[1:0] = a
619        self.assertEqual(
620            a,
621            array.array(self.typecode, self.example[:1] + self.example + self.example[1:])
622        )
623
624        a = array.array(self.typecode, self.example)
625        a[2000:1000] = a
626        self.assertEqual(
627            a,
628            array.array(self.typecode, 2*self.example)
629        )
630
631        a = array.array(self.typecode, self.example)
632        self.assertRaises(TypeError, a.__setslice__, 0, 0, None)
633        self.assertRaises(TypeError, a.__setitem__, slice(0, 0), None)
634        self.assertRaises(TypeError, a.__setitem__, slice(0, 1), None)
635
636        b = array.array(self.badtypecode())
637        self.assertRaises(TypeError, a.__setslice__, 0, 0, b)
638        self.assertRaises(TypeError, a.__setitem__, slice(0, 0), b)
639        self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
640
641    def test_extended_set_del_slice(self):
642        indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
643        for start in indices:
644            for stop in indices:
645                # Everything except the initial 0 (invalid step)
646                for step in indices[1:]:
647                    a = array.array(self.typecode, self.example)
648                    L = list(a)
649                    # Make sure we have a slice of exactly the right length,
650                    # but with (hopefully) different data.
651                    data = L[start:stop:step]
652                    data.reverse()
653                    L[start:stop:step] = data
654                    a[start:stop:step] = array.array(self.typecode, data)
655                    self.assertEqual(a, array.array(self.typecode, L))
656
657                    del L[start:stop:step]
658                    del a[start:stop:step]
659                    self.assertEqual(a, array.array(self.typecode, L))
660
661    def test_index(self):
662        example = 2*self.example
663        a = array.array(self.typecode, example)
664        self.assertRaises(TypeError, a.index)
665        for x in example:
666            self.assertEqual(a.index(x), example.index(x))
667        self.assertRaises(ValueError, a.index, None)
668        self.assertRaises(ValueError, a.index, self.outside)
669
670    def test_count(self):
671        example = 2*self.example
672        a = array.array(self.typecode, example)
673        self.assertRaises(TypeError, a.count)
674        for x in example:
675            self.assertEqual(a.count(x), example.count(x))
676        self.assertEqual(a.count(self.outside), 0)
677        self.assertEqual(a.count(None), 0)
678
679    def test_remove(self):
680        for x in self.example:
681            example = 2*self.example
682            a = array.array(self.typecode, example)
683            pos = example.index(x)
684            example2 = example[:pos] + example[pos+1:]
685            a.remove(x)
686            self.assertEqual(a, array.array(self.typecode, example2))
687
688        a = array.array(self.typecode, self.example)
689        self.assertRaises(ValueError, a.remove, self.outside)
690
691        self.assertRaises(ValueError, a.remove, None)
692
693    def test_pop(self):
694        a = array.array(self.typecode)
695        self.assertRaises(IndexError, a.pop)
696
697        a = array.array(self.typecode, 2*self.example)
698        self.assertRaises(TypeError, a.pop, 42, 42)
699        self.assertRaises(TypeError, a.pop, None)
700        self.assertRaises(IndexError, a.pop, len(a))
701        self.assertRaises(IndexError, a.pop, -len(a)-1)
702
703        self.assertEntryEqual(a.pop(0), self.example[0])
704        self.assertEqual(
705            a,
706            array.array(self.typecode, self.example[1:]+self.example)
707        )
708        self.assertEntryEqual(a.pop(1), self.example[2])
709        self.assertEqual(
710            a,
711            array.array(self.typecode, self.example[1:2]+self.example[3:]+self.example)
712        )
713        self.assertEntryEqual(a.pop(0), self.example[1])
714        self.assertEntryEqual(a.pop(), self.example[-1])
715        self.assertEqual(
716            a,
717            array.array(self.typecode, self.example[3:]+self.example[:-1])
718        )
719
720    def test_reverse(self):
721        a = array.array(self.typecode, self.example)
722        self.assertRaises(TypeError, a.reverse, 42)
723        a.reverse()
724        self.assertEqual(
725            a,
726            array.array(self.typecode, self.example[::-1])
727        )
728
729    def test_extend(self):
730        a = array.array(self.typecode, self.example)
731        self.assertRaises(TypeError, a.extend)
732        a.extend(array.array(self.typecode, self.example[::-1]))
733        self.assertEqual(
734            a,
735            array.array(self.typecode, self.example+self.example[::-1])
736        )
737
738        a = array.array(self.typecode, self.example)
739        a.extend(a)
740        self.assertEqual(
741            a,
742            array.array(self.typecode, self.example+self.example)
743        )
744
745        b = array.array(self.badtypecode())
746        self.assertRaises(TypeError, a.extend, b)
747
748        a = array.array(self.typecode, self.example)
749        a.extend(self.example[::-1])
750        self.assertEqual(
751            a,
752            array.array(self.typecode, self.example+self.example[::-1])
753        )
754
755    def test_constructor_with_iterable_argument(self):
756        a = array.array(self.typecode, iter(self.example))
757        b = array.array(self.typecode, self.example)
758        self.assertEqual(a, b)
759
760        # non-iterable argument
761        self.assertRaises(TypeError, array.array, self.typecode, 10)
762
763        # pass through errors raised in __iter__
764        class A:
765            def __iter__(self):
766                raise UnicodeError
767        self.assertRaises(UnicodeError, array.array, self.typecode, A())
768
769        # pass through errors raised in next()
770        def B():
771            raise UnicodeError
772            yield None
773        self.assertRaises(UnicodeError, array.array, self.typecode, B())
774
775    def test_coveritertraverse(self):
776        try:
777            import gc
778        except ImportError:
779            self.skipTest('gc module not available')
780        a = array.array(self.typecode)
781        l = [iter(a)]
782        l.append(l)
783        gc.collect()
784
785    def test_buffer(self):
786        a = array.array(self.typecode, self.example)
787        with test_support.check_py3k_warnings():
788            b = buffer(a)
789        self.assertEqual(b[0], a.tostring()[0])
790
791    def test_weakref(self):
792        s = array.array(self.typecode, self.example)
793        p = proxy(s)
794        self.assertEqual(p.tostring(), s.tostring())
795        s = None
796        self.assertRaises(ReferenceError, len, p)
797
798    @unittest.skipUnless(hasattr(sys, 'getrefcount'),
799                         'test needs sys.getrefcount()')
800    def test_bug_782369(self):
801        for i in range(10):
802            b = array.array('B', range(64))
803        rc = sys.getrefcount(10)
804        for i in range(10):
805            b = array.array('B', range(64))
806        self.assertEqual(rc, sys.getrefcount(10))
807
808    def test_subclass_with_kwargs(self):
809        # SF bug #1486663 -- this used to erroneously raise a TypeError
810        with warnings.catch_warnings():
811            warnings.filterwarnings("ignore", '', DeprecationWarning)
812            ArraySubclassWithKwargs('b', newarg=1)
813
814
815class StringTest(BaseTest):
816
817    def test_setitem(self):
818        super(StringTest, self).test_setitem()
819        a = array.array(self.typecode, self.example)
820        self.assertRaises(TypeError, a.__setitem__, 0, self.example[:2])
821
822class CharacterTest(StringTest):
823    typecode = 'c'
824    example = '\x01azAZ\x00\xfe'
825    smallerexample = '\x01azAY\x00\xfe'
826    biggerexample = '\x01azAZ\x00\xff'
827    outside = '\x33'
828    minitemsize = 1
829
830    def test_subbclassing(self):
831        class EditableString(array.array):
832            def __new__(cls, s, *args, **kwargs):
833                return array.array.__new__(cls, 'c', s)
834
835            def __init__(self, s, color='blue'):
836                self.color = color
837
838            def strip(self):
839                self[:] = array.array('c', self.tostring().strip())
840
841            def __repr__(self):
842                return 'EditableString(%r)' % self.tostring()
843
844        s = EditableString("\ttest\r\n")
845        s.strip()
846        self.assertEqual(s.tostring(), "test")
847
848        self.assertEqual(s.color, "blue")
849        s.color = "red"
850        self.assertEqual(s.color, "red")
851        self.assertEqual(s.__dict__.keys(), ["color"])
852
853    @test_support.requires_unicode
854    def test_nounicode(self):
855        a = array.array(self.typecode, self.example)
856        self.assertRaises(ValueError, a.fromunicode, unicode(''))
857        self.assertRaises(ValueError, a.tounicode)
858
859tests.append(CharacterTest)
860
861if test_support.have_unicode:
862    class UnicodeTest(StringTest):
863        typecode = 'u'
864        example = unicode(r'\x01\u263a\x00\ufeff', 'unicode-escape')
865        smallerexample = unicode(r'\x01\u263a\x00\ufefe', 'unicode-escape')
866        biggerexample = unicode(r'\x01\u263a\x01\ufeff', 'unicode-escape')
867        outside = unicode('\x33')
868        minitemsize = 2
869
870        def test_unicode(self):
871            self.assertRaises(TypeError, array.array, 'b', unicode('foo', 'ascii'))
872
873            a = array.array('u', unicode(r'\xa0\xc2\u1234', 'unicode-escape'))
874            a.fromunicode(unicode(' ', 'ascii'))
875            a.fromunicode(unicode('', 'ascii'))
876            a.fromunicode(unicode('', 'ascii'))
877            a.fromunicode(unicode(r'\x11abc\xff\u1234', 'unicode-escape'))
878            s = a.tounicode()
879            self.assertEqual(
880                s,
881                unicode(r'\xa0\xc2\u1234 \x11abc\xff\u1234', 'unicode-escape')
882            )
883
884            s = unicode(r'\x00="\'a\\b\x80\xff\u0000\u0001\u1234', 'unicode-escape')
885            a = array.array('u', s)
886            self.assertEqual(
887                repr(a),
888                r"""array('u', u'\x00="\'a\\b\x80\xff\x00\x01\u1234')"""
889            )
890
891            self.assertRaises(TypeError, a.fromunicode)
892
893    tests.append(UnicodeTest)
894
895class NumberTest(BaseTest):
896
897    def test_extslice(self):
898        a = array.array(self.typecode, range(5))
899        self.assertEqual(a[::], a)
900        self.assertEqual(a[::2], array.array(self.typecode, [0,2,4]))
901        self.assertEqual(a[1::2], array.array(self.typecode, [1,3]))
902        self.assertEqual(a[::-1], array.array(self.typecode, [4,3,2,1,0]))
903        self.assertEqual(a[::-2], array.array(self.typecode, [4,2,0]))
904        self.assertEqual(a[3::-2], array.array(self.typecode, [3,1]))
905        self.assertEqual(a[-100:100:], a)
906        self.assertEqual(a[100:-100:-1], a[::-1])
907        self.assertEqual(a[-100L:100L:2L], array.array(self.typecode, [0,2,4]))
908        self.assertEqual(a[1000:2000:2], array.array(self.typecode, []))
909        self.assertEqual(a[-1000:-2000:-2], array.array(self.typecode, []))
910
911    def test_delslice(self):
912        a = array.array(self.typecode, range(5))
913        del a[::2]
914        self.assertEqual(a, array.array(self.typecode, [1,3]))
915        a = array.array(self.typecode, range(5))
916        del a[1::2]
917        self.assertEqual(a, array.array(self.typecode, [0,2,4]))
918        a = array.array(self.typecode, range(5))
919        del a[1::-2]
920        self.assertEqual(a, array.array(self.typecode, [0,2,3,4]))
921        a = array.array(self.typecode, range(10))
922        del a[::1000]
923        self.assertEqual(a, array.array(self.typecode, [1,2,3,4,5,6,7,8,9]))
924        # test issue7788
925        a = array.array(self.typecode, range(10))
926        del a[9::1<<333]
927
928    def test_assignment(self):
929        a = array.array(self.typecode, range(10))
930        a[::2] = array.array(self.typecode, [42]*5)
931        self.assertEqual(a, array.array(self.typecode, [42, 1, 42, 3, 42, 5, 42, 7, 42, 9]))
932        a = array.array(self.typecode, range(10))
933        a[::-4] = array.array(self.typecode, [10]*3)
934        self.assertEqual(a, array.array(self.typecode, [0, 10, 2, 3, 4, 10, 6, 7, 8 ,10]))
935        a = array.array(self.typecode, range(4))
936        a[::-1] = a
937        self.assertEqual(a, array.array(self.typecode, [3, 2, 1, 0]))
938        a = array.array(self.typecode, range(10))
939        b = a[:]
940        c = a[:]
941        ins = array.array(self.typecode, range(2))
942        a[2:3] = ins
943        b[slice(2,3)] = ins
944        c[2:3:] = ins
945
946    def test_iterationcontains(self):
947        a = array.array(self.typecode, range(10))
948        self.assertEqual(list(a), range(10))
949        b = array.array(self.typecode, [20])
950        self.assertEqual(a[-1] in a, True)
951        self.assertEqual(b[0] not in a, True)
952
953    def check_overflow(self, lower, upper):
954        # method to be used by subclasses
955
956        # should not overflow assigning lower limit
957        a = array.array(self.typecode, [lower])
958        a[0] = lower
959        # should overflow assigning less than lower limit
960        self.assertRaises(OverflowError, array.array, self.typecode, [lower-1])
961        self.assertRaises(OverflowError, a.__setitem__, 0, lower-1)
962        # should not overflow assigning upper limit
963        a = array.array(self.typecode, [upper])
964        a[0] = upper
965        # should overflow assigning more than upper limit
966        self.assertRaises(OverflowError, array.array, self.typecode, [upper+1])
967        self.assertRaises(OverflowError, a.__setitem__, 0, upper+1)
968
969    def test_subclassing(self):
970        typecode = self.typecode
971        class ExaggeratingArray(array.array):
972            __slots__ = ['offset']
973
974            def __new__(cls, typecode, data, offset):
975                return array.array.__new__(cls, typecode, data)
976
977            def __init__(self, typecode, data, offset):
978                self.offset = offset
979
980            def __getitem__(self, i):
981                return array.array.__getitem__(self, i) + self.offset
982
983        a = ExaggeratingArray(self.typecode, [3, 6, 7, 11], 4)
984        self.assertEntryEqual(a[0], 7)
985
986        self.assertRaises(AttributeError, setattr, a, "color", "blue")
987
988class SignedNumberTest(NumberTest):
989    example = [-1, 0, 1, 42, 0x7f]
990    smallerexample = [-1, 0, 1, 42, 0x7e]
991    biggerexample = [-1, 0, 1, 43, 0x7f]
992    outside = 23
993
994    def test_overflow(self):
995        a = array.array(self.typecode)
996        lower = -1 * long(pow(2, a.itemsize * 8 - 1))
997        upper = long(pow(2, a.itemsize * 8 - 1)) - 1L
998        self.check_overflow(lower, upper)
999
1000class UnsignedNumberTest(NumberTest):
1001    example = [0, 1, 17, 23, 42, 0xff]
1002    smallerexample = [0, 1, 17, 23, 42, 0xfe]
1003    biggerexample = [0, 1, 17, 23, 43, 0xff]
1004    outside = 0xaa
1005
1006    def test_overflow(self):
1007        a = array.array(self.typecode)
1008        lower = 0
1009        upper = long(pow(2, a.itemsize * 8)) - 1L
1010        self.check_overflow(lower, upper)
1011
1012    @test_support.cpython_only
1013    def test_sizeof_with_buffer(self):
1014        a = array.array(self.typecode, self.example)
1015        basesize = test_support.calcvobjsize('4P')
1016        buffer_size = a.buffer_info()[1] * a.itemsize
1017        test_support.check_sizeof(self, a, basesize + buffer_size)
1018
1019    @test_support.cpython_only
1020    def test_sizeof_without_buffer(self):
1021        a = array.array(self.typecode)
1022        basesize = test_support.calcvobjsize('4P')
1023        test_support.check_sizeof(self, a, basesize)
1024
1025
1026class ByteTest(SignedNumberTest):
1027    typecode = 'b'
1028    minitemsize = 1
1029tests.append(ByteTest)
1030
1031class UnsignedByteTest(UnsignedNumberTest):
1032    typecode = 'B'
1033    minitemsize = 1
1034tests.append(UnsignedByteTest)
1035
1036class ShortTest(SignedNumberTest):
1037    typecode = 'h'
1038    minitemsize = 2
1039tests.append(ShortTest)
1040
1041class UnsignedShortTest(UnsignedNumberTest):
1042    typecode = 'H'
1043    minitemsize = 2
1044tests.append(UnsignedShortTest)
1045
1046class IntTest(SignedNumberTest):
1047    typecode = 'i'
1048    minitemsize = 2
1049tests.append(IntTest)
1050
1051class UnsignedIntTest(UnsignedNumberTest):
1052    typecode = 'I'
1053    minitemsize = 2
1054tests.append(UnsignedIntTest)
1055
1056class LongTest(SignedNumberTest):
1057    typecode = 'l'
1058    minitemsize = 4
1059tests.append(LongTest)
1060
1061class UnsignedLongTest(UnsignedNumberTest):
1062    typecode = 'L'
1063    minitemsize = 4
1064tests.append(UnsignedLongTest)
1065
1066
1067@test_support.requires_unicode
1068class UnicodeTypecodeTest(unittest.TestCase):
1069    def test_unicode_typecode(self):
1070        for typecode in typecodes:
1071            a = array.array(unicode(typecode))
1072            self.assertEqual(a.typecode, typecode)
1073            self.assertIs(type(a.typecode), str)
1074tests.append(UnicodeTypecodeTest)
1075
1076
1077class FPTest(NumberTest):
1078    example = [-42.0, 0, 42, 1e5, -1e10]
1079    smallerexample = [-42.0, 0, 42, 1e5, -2e10]
1080    biggerexample = [-42.0, 0, 42, 1e5, 1e10]
1081    outside = 23
1082
1083    def assertEntryEqual(self, entry1, entry2):
1084        self.assertAlmostEqual(entry1, entry2)
1085
1086    def test_byteswap(self):
1087        a = array.array(self.typecode, self.example)
1088        self.assertRaises(TypeError, a.byteswap, 42)
1089        if a.itemsize in (1, 2, 4, 8):
1090            b = array.array(self.typecode, self.example)
1091            b.byteswap()
1092            if a.itemsize==1:
1093                self.assertEqual(a, b)
1094            else:
1095                # On alphas treating the byte swapped bit patters as
1096                # floats/doubles results in floating point exceptions
1097                # => compare the 8bit string values instead
1098                self.assertNotEqual(a.tostring(), b.tostring())
1099            b.byteswap()
1100            self.assertEqual(a, b)
1101
1102class FloatTest(FPTest):
1103    typecode = 'f'
1104    minitemsize = 4
1105tests.append(FloatTest)
1106
1107class DoubleTest(FPTest):
1108    typecode = 'd'
1109    minitemsize = 8
1110
1111    def test_alloc_overflow(self):
1112        from sys import maxsize
1113        a = array.array('d', [-1]*65536)
1114        try:
1115            a *= maxsize//65536 + 1
1116        except MemoryError:
1117            pass
1118        else:
1119            self.fail("Array of size > maxsize created - MemoryError expected")
1120        b = array.array('d', [ 2.71828183, 3.14159265, -1])
1121        try:
1122            b * (maxsize//3 + 1)
1123        except MemoryError:
1124            pass
1125        else:
1126            self.fail("Array of size > maxsize created - MemoryError expected")
1127
1128tests.append(DoubleTest)
1129
1130def test_main(verbose=None):
1131    import sys
1132
1133    test_support.run_unittest(*tests)
1134
1135    # verify reference counting
1136    if verbose and hasattr(sys, "gettotalrefcount"):
1137        import gc
1138        counts = [None] * 5
1139        for i in xrange(len(counts)):
1140            test_support.run_unittest(*tests)
1141            gc.collect()
1142            counts[i] = sys.gettotalrefcount()
1143        print counts
1144
1145if __name__ == "__main__":
1146    test_main(verbose=True)
1147