1import unittest 2from test.support import bigmemtest, _2G 3import sys 4from ctypes import * 5 6from ctypes.test import need_symbol 7 8formats = "bBhHiIlLqQfd" 9 10formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ 11 c_long, c_ulonglong, c_float, c_double, c_longdouble 12 13class ArrayTestCase(unittest.TestCase): 14 def test_simple(self): 15 # create classes holding simple numeric types, and check 16 # various properties. 17 18 init = list(range(15, 25)) 19 20 for fmt in formats: 21 alen = len(init) 22 int_array = ARRAY(fmt, alen) 23 24 ia = int_array(*init) 25 # length of instance ok? 26 self.assertEqual(len(ia), alen) 27 28 # slot values ok? 29 values = [ia[i] for i in range(alen)] 30 self.assertEqual(values, init) 31 32 # out-of-bounds accesses should be caught 33 with self.assertRaises(IndexError): ia[alen] 34 with self.assertRaises(IndexError): ia[-alen-1] 35 36 # change the items 37 from operator import setitem 38 new_values = list(range(42, 42+alen)) 39 [setitem(ia, n, new_values[n]) for n in range(alen)] 40 values = [ia[i] for i in range(alen)] 41 self.assertEqual(values, new_values) 42 43 # are the items initialized to 0? 44 ia = int_array() 45 values = [ia[i] for i in range(alen)] 46 self.assertEqual(values, [0] * alen) 47 48 # Too many initializers should be caught 49 self.assertRaises(IndexError, int_array, *range(alen*2)) 50 51 CharArray = ARRAY(c_char, 3) 52 53 ca = CharArray(b"a", b"b", b"c") 54 55 # Should this work? It doesn't: 56 # CharArray("abc") 57 self.assertRaises(TypeError, CharArray, "abc") 58 59 self.assertEqual(ca[0], b"a") 60 self.assertEqual(ca[1], b"b") 61 self.assertEqual(ca[2], b"c") 62 self.assertEqual(ca[-3], b"a") 63 self.assertEqual(ca[-2], b"b") 64 self.assertEqual(ca[-1], b"c") 65 66 self.assertEqual(len(ca), 3) 67 68 # cannot delete items 69 from operator import delitem 70 self.assertRaises(TypeError, delitem, ca, 0) 71 72 def test_step_overflow(self): 73 a = (c_int * 5)() 74 a[3::sys.maxsize] = (1,) 75 self.assertListEqual(a[3::sys.maxsize], [1]) 76 a = (c_char * 5)() 77 a[3::sys.maxsize] = b"A" 78 self.assertEqual(a[3::sys.maxsize], b"A") 79 a = (c_wchar * 5)() 80 a[3::sys.maxsize] = u"X" 81 self.assertEqual(a[3::sys.maxsize], u"X") 82 83 def test_numeric_arrays(self): 84 85 alen = 5 86 87 numarray = ARRAY(c_int, alen) 88 89 na = numarray() 90 values = [na[i] for i in range(alen)] 91 self.assertEqual(values, [0] * alen) 92 93 na = numarray(*[c_int()] * alen) 94 values = [na[i] for i in range(alen)] 95 self.assertEqual(values, [0]*alen) 96 97 na = numarray(1, 2, 3, 4, 5) 98 values = [i for i in na] 99 self.assertEqual(values, [1, 2, 3, 4, 5]) 100 101 na = numarray(*map(c_int, (1, 2, 3, 4, 5))) 102 values = [i for i in na] 103 self.assertEqual(values, [1, 2, 3, 4, 5]) 104 105 def test_classcache(self): 106 self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4)) 107 self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3)) 108 109 def test_from_address(self): 110 # Failed with 0.9.8, reported by JUrner 111 p = create_string_buffer(b"foo") 112 sz = (c_char * 3).from_address(addressof(p)) 113 self.assertEqual(sz[:], b"foo") 114 self.assertEqual(sz[::], b"foo") 115 self.assertEqual(sz[::-1], b"oof") 116 self.assertEqual(sz[::3], b"f") 117 self.assertEqual(sz[1:4:2], b"o") 118 self.assertEqual(sz.value, b"foo") 119 120 @need_symbol('create_unicode_buffer') 121 def test_from_addressW(self): 122 p = create_unicode_buffer("foo") 123 sz = (c_wchar * 3).from_address(addressof(p)) 124 self.assertEqual(sz[:], "foo") 125 self.assertEqual(sz[::], "foo") 126 self.assertEqual(sz[::-1], "oof") 127 self.assertEqual(sz[::3], "f") 128 self.assertEqual(sz[1:4:2], "o") 129 self.assertEqual(sz.value, "foo") 130 131 def test_cache(self): 132 # Array types are cached internally in the _ctypes extension, 133 # in a WeakValueDictionary. Make sure the array type is 134 # removed from the cache when the itemtype goes away. This 135 # test will not fail, but will show a leak in the testsuite. 136 137 # Create a new type: 138 class my_int(c_int): 139 pass 140 # Create a new array type based on it: 141 t1 = my_int * 1 142 t2 = my_int * 1 143 self.assertIs(t1, t2) 144 145 def test_subclass(self): 146 class T(Array): 147 _type_ = c_int 148 _length_ = 13 149 class U(T): 150 pass 151 class V(U): 152 pass 153 class W(V): 154 pass 155 class X(T): 156 _type_ = c_short 157 class Y(T): 158 _length_ = 187 159 160 for c in [T, U, V, W]: 161 self.assertEqual(c._type_, c_int) 162 self.assertEqual(c._length_, 13) 163 self.assertEqual(c()._type_, c_int) 164 self.assertEqual(c()._length_, 13) 165 166 self.assertEqual(X._type_, c_short) 167 self.assertEqual(X._length_, 13) 168 self.assertEqual(X()._type_, c_short) 169 self.assertEqual(X()._length_, 13) 170 171 self.assertEqual(Y._type_, c_int) 172 self.assertEqual(Y._length_, 187) 173 self.assertEqual(Y()._type_, c_int) 174 self.assertEqual(Y()._length_, 187) 175 176 def test_bad_subclass(self): 177 with self.assertRaises(AttributeError): 178 class T(Array): 179 pass 180 with self.assertRaises(AttributeError): 181 class T(Array): 182 _type_ = c_int 183 with self.assertRaises(AttributeError): 184 class T(Array): 185 _length_ = 13 186 187 def test_bad_length(self): 188 with self.assertRaises(ValueError): 189 class T(Array): 190 _type_ = c_int 191 _length_ = - sys.maxsize * 2 192 with self.assertRaises(ValueError): 193 class T(Array): 194 _type_ = c_int 195 _length_ = -1 196 with self.assertRaises(TypeError): 197 class T(Array): 198 _type_ = c_int 199 _length_ = 1.87 200 with self.assertRaises(OverflowError): 201 class T(Array): 202 _type_ = c_int 203 _length_ = sys.maxsize * 2 204 205 def test_zero_length(self): 206 # _length_ can be zero. 207 class T(Array): 208 _type_ = c_int 209 _length_ = 0 210 211 def test_empty_element_struct(self): 212 class EmptyStruct(Structure): 213 _fields_ = [] 214 215 obj = (EmptyStruct * 2)() # bpo37188: Floating point exception 216 self.assertEqual(sizeof(obj), 0) 217 218 def test_empty_element_array(self): 219 class EmptyArray(Array): 220 _type_ = c_int 221 _length_ = 0 222 223 obj = (EmptyArray * 2)() # bpo37188: Floating point exception 224 self.assertEqual(sizeof(obj), 0) 225 226 def test_bpo36504_signed_int_overflow(self): 227 # The overflow check in PyCArrayType_new() could cause signed integer 228 # overflow. 229 with self.assertRaises(OverflowError): 230 c_char * sys.maxsize * 2 231 232 @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') 233 @bigmemtest(size=_2G, memuse=1, dry_run=False) 234 def test_large_array(self, size): 235 c_char * size 236 237if __name__ == '__main__': 238 unittest.main() 239