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