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