Home | History | Annotate | Download | only in test
      1 import unittest
      2 from ctypes import *
      3 
      4 from ctypes.test import need_symbol
      5 
      6 formats = "bBhHiIlLqQfd"
      7 
      8 formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
      9           c_long, c_ulonglong, c_float, c_double, c_longdouble
     10 
     11 class ArrayTestCase(unittest.TestCase):
     12     def test_simple(self):
     13         # create classes holding simple numeric types, and check
     14         # various properties.
     15 
     16         init = list(range(15, 25))
     17 
     18         for fmt in formats:
     19             alen = len(init)
     20             int_array = ARRAY(fmt, alen)
     21 
     22             ia = int_array(*init)
     23             # length of instance ok?
     24             self.assertEqual(len(ia), alen)
     25 
     26             # slot values ok?
     27             values = [ia[i] for i in range(alen)]
     28             self.assertEqual(values, init)
     29 
     30             # out-of-bounds accesses should be caught
     31             with self.assertRaises(IndexError): ia[alen]
     32             with self.assertRaises(IndexError): ia[-alen-1]
     33 
     34             # change the items
     35             from operator import setitem
     36             new_values = list(range(42, 42+alen))
     37             [setitem(ia, n, new_values[n]) for n in range(alen)]
     38             values = [ia[i] for i in range(alen)]
     39             self.assertEqual(values, new_values)
     40 
     41             # are the items initialized to 0?
     42             ia = int_array()
     43             values = [ia[i] for i in range(alen)]
     44             self.assertEqual(values, [0] * alen)
     45 
     46             # Too many initializers should be caught
     47             self.assertRaises(IndexError, int_array, *range(alen*2))
     48 
     49         CharArray = ARRAY(c_char, 3)
     50 
     51         ca = CharArray(b"a", b"b", b"c")
     52 
     53         # Should this work? It doesn't:
     54         # CharArray("abc")
     55         self.assertRaises(TypeError, CharArray, "abc")
     56 
     57         self.assertEqual(ca[0], b"a")
     58         self.assertEqual(ca[1], b"b")
     59         self.assertEqual(ca[2], b"c")
     60         self.assertEqual(ca[-3], b"a")
     61         self.assertEqual(ca[-2], b"b")
     62         self.assertEqual(ca[-1], b"c")
     63 
     64         self.assertEqual(len(ca), 3)
     65 
     66         # cannot delete items
     67         from operator import delitem
     68         self.assertRaises(TypeError, delitem, ca, 0)
     69 
     70     def test_numeric_arrays(self):
     71 
     72         alen = 5
     73 
     74         numarray = ARRAY(c_int, alen)
     75 
     76         na = numarray()
     77         values = [na[i] for i in range(alen)]
     78         self.assertEqual(values, [0] * alen)
     79 
     80         na = numarray(*[c_int()] * alen)
     81         values = [na[i] for i in range(alen)]
     82         self.assertEqual(values, [0]*alen)
     83 
     84         na = numarray(1, 2, 3, 4, 5)
     85         values = [i for i in na]
     86         self.assertEqual(values, [1, 2, 3, 4, 5])
     87 
     88         na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
     89         values = [i for i in na]
     90         self.assertEqual(values, [1, 2, 3, 4, 5])
     91 
     92     def test_classcache(self):
     93         self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4))
     94         self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3))
     95 
     96     def test_from_address(self):
     97         # Failed with 0.9.8, reported by JUrner
     98         p = create_string_buffer(b"foo")
     99         sz = (c_char * 3).from_address(addressof(p))
    100         self.assertEqual(sz[:], b"foo")
    101         self.assertEqual(sz[::], b"foo")
    102         self.assertEqual(sz[::-1], b"oof")
    103         self.assertEqual(sz[::3], b"f")
    104         self.assertEqual(sz[1:4:2], b"o")
    105         self.assertEqual(sz.value, b"foo")
    106 
    107     @need_symbol('create_unicode_buffer')
    108     def test_from_addressW(self):
    109         p = create_unicode_buffer("foo")
    110         sz = (c_wchar * 3).from_address(addressof(p))
    111         self.assertEqual(sz[:], "foo")
    112         self.assertEqual(sz[::], "foo")
    113         self.assertEqual(sz[::-1], "oof")
    114         self.assertEqual(sz[::3], "f")
    115         self.assertEqual(sz[1:4:2], "o")
    116         self.assertEqual(sz.value, "foo")
    117 
    118     def test_cache(self):
    119         # Array types are cached internally in the _ctypes extension,
    120         # in a WeakValueDictionary.  Make sure the array type is
    121         # removed from the cache when the itemtype goes away.  This
    122         # test will not fail, but will show a leak in the testsuite.
    123 
    124         # Create a new type:
    125         class my_int(c_int):
    126             pass
    127         # Create a new array type based on it:
    128         t1 = my_int * 1
    129         t2 = my_int * 1
    130         self.assertIs(t1, t2)
    131 
    132     def test_subclass(self):
    133         class T(Array):
    134             _type_ = c_int
    135             _length_ = 13
    136         class U(T):
    137             pass
    138         class V(U):
    139             pass
    140         class W(V):
    141             pass
    142         class X(T):
    143             _type_ = c_short
    144         class Y(T):
    145             _length_ = 187
    146 
    147         for c in [T, U, V, W]:
    148             self.assertEqual(c._type_, c_int)
    149             self.assertEqual(c._length_, 13)
    150             self.assertEqual(c()._type_, c_int)
    151             self.assertEqual(c()._length_, 13)
    152 
    153         self.assertEqual(X._type_, c_short)
    154         self.assertEqual(X._length_, 13)
    155         self.assertEqual(X()._type_, c_short)
    156         self.assertEqual(X()._length_, 13)
    157 
    158         self.assertEqual(Y._type_, c_int)
    159         self.assertEqual(Y._length_, 187)
    160         self.assertEqual(Y()._type_, c_int)
    161         self.assertEqual(Y()._length_, 187)
    162 
    163     def test_bad_subclass(self):
    164         import sys
    165 
    166         with self.assertRaises(AttributeError):
    167             class T(Array):
    168                 pass
    169         with self.assertRaises(AttributeError):
    170             class T(Array):
    171                 _type_ = c_int
    172         with self.assertRaises(AttributeError):
    173             class T(Array):
    174                 _length_ = 13
    175         with self.assertRaises(OverflowError):
    176             class T(Array):
    177                 _type_ = c_int
    178                 _length_ = sys.maxsize * 2
    179         with self.assertRaises(AttributeError):
    180             class T(Array):
    181                 _type_ = c_int
    182                 _length_ = 1.87
    183 
    184 if __name__ == '__main__':
    185     unittest.main()
    186