blob: c4a651c9666d7ccc96f32aaf2fbb1598f861faac [file] [log] [blame]
Thomas Hellerbabddfc2006-03-08 19:56:54 +00001import unittest
2from ctypes import *
Zachary Ware9422df02014-06-13 13:44:39 -05003from ctypes.test import need_symbol
Thomas Hellerbabddfc2006-03-08 19:56:54 +00004from struct import calcsize
Serhiy Storchaka441d30f2013-01-19 12:26:26 +02005import _testcapi
Thomas Hellerbabddfc2006-03-08 19:56:54 +00006
7class SubclassesTest(unittest.TestCase):
8 def test_subclass(self):
9 class X(Structure):
10 _fields_ = [("a", c_int)]
11
12 class Y(X):
13 _fields_ = [("b", c_int)]
14
15 class Z(X):
16 pass
17
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000018 self.assertEqual(sizeof(X), sizeof(c_int))
19 self.assertEqual(sizeof(Y), sizeof(c_int)*2)
20 self.assertEqual(sizeof(Z), sizeof(c_int))
21 self.assertEqual(X._fields_, [("a", c_int)])
22 self.assertEqual(Y._fields_, [("b", c_int)])
23 self.assertEqual(Z._fields_, [("a", c_int)])
Thomas Hellerbabddfc2006-03-08 19:56:54 +000024
25 def test_subclass_delayed(self):
26 class X(Structure):
27 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000028 self.assertEqual(sizeof(X), 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000029 X._fields_ = [("a", c_int)]
30
31 class Y(X):
32 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000033 self.assertEqual(sizeof(Y), sizeof(X))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000034 Y._fields_ = [("b", c_int)]
35
36 class Z(X):
37 pass
38
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000039 self.assertEqual(sizeof(X), sizeof(c_int))
40 self.assertEqual(sizeof(Y), sizeof(c_int)*2)
41 self.assertEqual(sizeof(Z), sizeof(c_int))
42 self.assertEqual(X._fields_, [("a", c_int)])
43 self.assertEqual(Y._fields_, [("b", c_int)])
44 self.assertEqual(Z._fields_, [("a", c_int)])
Thomas Hellerbabddfc2006-03-08 19:56:54 +000045
46class StructureTestCase(unittest.TestCase):
47 formats = {"c": c_char,
48 "b": c_byte,
49 "B": c_ubyte,
50 "h": c_short,
51 "H": c_ushort,
52 "i": c_int,
53 "I": c_uint,
54 "l": c_long,
55 "L": c_ulong,
56 "q": c_longlong,
57 "Q": c_ulonglong,
58 "f": c_float,
59 "d": c_double,
60 }
Tim Peterse8d09e52006-03-09 01:15:05 +000061
Thomas Hellerbabddfc2006-03-08 19:56:54 +000062 def test_simple_structs(self):
63 for code, tp in self.formats.items():
64 class X(Structure):
65 _fields_ = [("x", c_char),
66 ("y", tp)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000067 self.assertEqual((sizeof(X), code),
Thomas Hellerbabddfc2006-03-08 19:56:54 +000068 (calcsize("c%c0%c" % (code, code)), code))
69
70 def test_unions(self):
71 for code, tp in self.formats.items():
72 class X(Union):
73 _fields_ = [("x", c_char),
74 ("y", tp)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000075 self.assertEqual((sizeof(X), code),
Thomas Hellerbabddfc2006-03-08 19:56:54 +000076 (calcsize("%c" % (code)), code))
77
78 def test_struct_alignment(self):
79 class X(Structure):
80 _fields_ = [("x", c_char * 3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000081 self.assertEqual(alignment(X), calcsize("s"))
82 self.assertEqual(sizeof(X), calcsize("3s"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000083
84 class Y(Structure):
85 _fields_ = [("x", c_char * 3),
86 ("y", c_int)]
Benjamin Petersonfda33552014-03-16 10:07:26 +010087 self.assertEqual(alignment(Y), alignment(c_int))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000088 self.assertEqual(sizeof(Y), calcsize("3si"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000089
90 class SI(Structure):
91 _fields_ = [("a", X),
92 ("b", Y)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000093 self.assertEqual(alignment(SI), max(alignment(Y), alignment(X)))
94 self.assertEqual(sizeof(SI), calcsize("3s0i 3si 0i"))
Tim Peterse8d09e52006-03-09 01:15:05 +000095
Thomas Hellerbabddfc2006-03-08 19:56:54 +000096 class IS(Structure):
97 _fields_ = [("b", Y),
98 ("a", X)]
99
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000100 self.assertEqual(alignment(SI), max(alignment(X), alignment(Y)))
101 self.assertEqual(sizeof(IS), calcsize("3si 3s 0i"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000102
103 class XX(Structure):
104 _fields_ = [("a", X),
105 ("b", X)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000106 self.assertEqual(alignment(XX), alignment(X))
107 self.assertEqual(sizeof(XX), calcsize("3s 3s 0s"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000108
Martin Pantereb995702016-07-28 01:11:04 +0000109 def test_empty(self):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000110 # I had problems with these
111 #
Ezio Melottib5bc3532013-08-17 16:11:40 +0300112 # Although these are pathological cases: Empty Structures!
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000113 class X(Structure):
114 _fields_ = []
115
116 class Y(Union):
117 _fields_ = []
118
119 # Is this really the correct alignment, or should it be 0?
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000120 self.assertTrue(alignment(X) == alignment(Y) == 1)
121 self.assertTrue(sizeof(X) == sizeof(Y) == 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000122
123 class XX(Structure):
124 _fields_ = [("a", X),
125 ("b", X)]
126
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000127 self.assertEqual(alignment(XX), 1)
128 self.assertEqual(sizeof(XX), 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000129
130 def test_fields(self):
131 # test the offset and size attributes of Structure/Unoin fields.
132 class X(Structure):
133 _fields_ = [("x", c_int),
134 ("y", c_char)]
135
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000136 self.assertEqual(X.x.offset, 0)
137 self.assertEqual(X.x.size, sizeof(c_int))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000138
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000139 self.assertEqual(X.y.offset, sizeof(c_int))
140 self.assertEqual(X.y.size, sizeof(c_char))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000141
142 # readonly
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000143 self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
144 self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000145
146 class X(Union):
147 _fields_ = [("x", c_int),
148 ("y", c_char)]
149
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000150 self.assertEqual(X.x.offset, 0)
151 self.assertEqual(X.x.size, sizeof(c_int))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000152
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000153 self.assertEqual(X.y.offset, 0)
154 self.assertEqual(X.y.size, sizeof(c_char))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000155
156 # readonly
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000157 self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
158 self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000159
160 # XXX Should we check nested data types also?
161 # offset is always relative to the class...
162
163 def test_packed(self):
164 class X(Structure):
165 _fields_ = [("a", c_byte),
166 ("b", c_longlong)]
167 _pack_ = 1
168
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000169 self.assertEqual(sizeof(X), 9)
170 self.assertEqual(X.b.offset, 1)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000171
172 class X(Structure):
173 _fields_ = [("a", c_byte),
174 ("b", c_longlong)]
175 _pack_ = 2
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertEqual(sizeof(X), 10)
177 self.assertEqual(X.b.offset, 2)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000178
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000179 import struct
180 longlong_size = struct.calcsize("q")
181 longlong_align = struct.calcsize("bq") - longlong_size
182
183 class X(Structure):
184 _fields_ = [("a", c_byte),
185 ("b", c_longlong)]
Benjamin Petersonfda33552014-03-16 10:07:26 +0100186 _pack_ = 4
187 self.assertEqual(sizeof(X), min(4, longlong_align) + longlong_size)
188 self.assertEqual(X.b.offset, min(4, longlong_align))
189
190 class X(Structure):
191 _fields_ = [("a", c_byte),
192 ("b", c_longlong)]
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000193 _pack_ = 8
194
Benjamin Petersonfda33552014-03-16 10:07:26 +0100195 self.assertEqual(sizeof(X), min(8, longlong_align) + longlong_size)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000196 self.assertEqual(X.b.offset, min(8, longlong_align))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000197
198
199 d = {"_fields_": [("a", "b"),
200 ("b", "q")],
201 "_pack_": -1}
202 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
203
Serhiy Storchaka441d30f2013-01-19 12:26:26 +0200204 # Issue 15989
205 d = {"_fields_": [("a", c_byte)],
206 "_pack_": _testcapi.INT_MAX + 1}
207 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
208 d = {"_fields_": [("a", c_byte)],
209 "_pack_": _testcapi.UINT_MAX + 2}
210 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
211
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000212 def test_initializers(self):
213 class Person(Structure):
214 _fields_ = [("name", c_char*6),
215 ("age", c_int)]
216
217 self.assertRaises(TypeError, Person, 42)
Victor Stinner42746df2010-07-27 23:36:41 +0000218 self.assertRaises(ValueError, Person, b"asldkjaslkdjaslkdj")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000219 self.assertRaises(TypeError, Person, "Name", "HI")
220
221 # short enough
Victor Stinner42746df2010-07-27 23:36:41 +0000222 self.assertEqual(Person(b"12345", 5).name, b"12345")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000223 # exact fit
Victor Stinner42746df2010-07-27 23:36:41 +0000224 self.assertEqual(Person(b"123456", 5).name, b"123456")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000225 # too long
Victor Stinner42746df2010-07-27 23:36:41 +0000226 self.assertRaises(ValueError, Person, b"1234567", 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000227
Thomas Hellerff721222008-01-17 18:46:55 +0000228 def test_conflicting_initializers(self):
229 class POINT(Structure):
Serhiy Storchaka886a5f32016-06-18 09:58:24 +0300230 _fields_ = [("phi", c_float), ("rho", c_float)]
Thomas Hellerff721222008-01-17 18:46:55 +0000231 # conflicting positional and keyword args
Serhiy Storchaka886a5f32016-06-18 09:58:24 +0300232 self.assertRaisesRegex(TypeError, "phi", POINT, 2, 3, phi=4)
233 self.assertRaisesRegex(TypeError, "rho", POINT, 2, 3, rho=4)
Thomas Hellerff721222008-01-17 18:46:55 +0000234
235 # too many initializers
236 self.assertRaises(TypeError, POINT, 2, 3, 4)
Tim Peterse8d09e52006-03-09 01:15:05 +0000237
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000238 def test_keyword_initializers(self):
239 class POINT(Structure):
240 _fields_ = [("x", c_int), ("y", c_int)]
241 pt = POINT(1, 2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000242 self.assertEqual((pt.x, pt.y), (1, 2))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000243
244 pt = POINT(y=2, x=1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000245 self.assertEqual((pt.x, pt.y), (1, 2))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000246
247 def test_invalid_field_types(self):
248 class POINT(Structure):
249 pass
250 self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
251
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200252 def test_invalid_name(self):
253 # field name must be string
254 def declare_with_name(name):
255 class S(Structure):
256 _fields_ = [(name, c_int)]
257
258 self.assertRaises(TypeError, declare_with_name, b"x")
259
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000260 def test_intarray_fields(self):
261 class SomeInts(Structure):
262 _fields_ = [("a", c_int * 4)]
263
264 # can use tuple to initialize array (but not list!)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000265 self.assertEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
266 self.assertEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
267 self.assertEqual(SomeInts((1, 2)).a[::-1], [0, 0, 2, 1])
268 self.assertEqual(SomeInts((1, 2)).a[::2], [1, 0])
269 self.assertEqual(SomeInts((1, 2)).a[1:5:6], [2])
270 self.assertEqual(SomeInts((1, 2)).a[6:4:-1], [])
271 self.assertEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
272 self.assertEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000273 # too long
274 # XXX Should raise ValueError?, not RuntimeError
275 self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
276
277 def test_nested_initializers(self):
278 # test initializing nested structures
279 class Phone(Structure):
280 _fields_ = [("areacode", c_char*6),
281 ("number", c_char*12)]
282
283 class Person(Structure):
284 _fields_ = [("name", c_char * 12),
285 ("phone", Phone),
286 ("age", c_int)]
287
Victor Stinner42746df2010-07-27 23:36:41 +0000288 p = Person(b"Someone", (b"1234", b"5678"), 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000289
Victor Stinnerda0eca42010-06-11 21:50:30 +0000290 self.assertEqual(p.name, b"Someone")
291 self.assertEqual(p.phone.areacode, b"1234")
292 self.assertEqual(p.phone.number, b"5678")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000293 self.assertEqual(p.age, 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000294
Zachary Ware9422df02014-06-13 13:44:39 -0500295 @need_symbol('c_wchar')
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000296 def test_structures_with_wchar(self):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000297 class PersonW(Structure):
298 _fields_ = [("name", c_wchar * 12),
299 ("age", c_int)]
300
Victor Stinner42746df2010-07-27 23:36:41 +0000301 p = PersonW("Someone \xe9")
302 self.assertEqual(p.name, "Someone \xe9")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000303
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000304 self.assertEqual(PersonW("1234567890").name, "1234567890")
305 self.assertEqual(PersonW("12345678901").name, "12345678901")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000306 # exact fit
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000307 self.assertEqual(PersonW("123456789012").name, "123456789012")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000308 #too long
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000309 self.assertRaises(ValueError, PersonW, "1234567890123")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000310
311 def test_init_errors(self):
312 class Phone(Structure):
313 _fields_ = [("areacode", c_char*6),
314 ("number", c_char*12)]
315
316 class Person(Structure):
317 _fields_ = [("name", c_char * 12),
318 ("phone", Phone),
319 ("age", c_int)]
320
Victor Stinner42746df2010-07-27 23:36:41 +0000321 cls, msg = self.get_except(Person, b"Someone", (1, 2))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000322 self.assertEqual(cls, RuntimeError)
323 self.assertEqual(msg,
Martin v. Löwis250ad612008-04-07 05:43:42 +0000324 "(Phone) <class 'TypeError'>: "
Serhiy Storchaka4f06d602014-08-09 09:33:05 +0300325 "expected bytes, int found")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000326
Victor Stinner42746df2010-07-27 23:36:41 +0000327 cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c"))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000328 self.assertEqual(cls, RuntimeError)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000329 if issubclass(Exception, object):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000330 self.assertEqual(msg,
Martin v. Löwis250ad612008-04-07 05:43:42 +0000331 "(Phone) <class 'TypeError'>: too many initializers")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000332 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000333 self.assertEqual(msg, "(Phone) TypeError: too many initializers")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000334
Meador Inge1efb33a2011-10-03 21:44:22 -0500335 def test_huge_field_name(self):
336 # issue12881: segfault with large structure field names
337 def create_class(length):
338 class S(Structure):
339 _fields_ = [('x' * length, c_int)]
340
341 for length in [10 ** i for i in range(0, 8)]:
342 try:
343 create_class(length)
344 except MemoryError:
345 # MemoryErrors are OK, we just don't want to segfault
346 pass
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000347
348 def get_except(self, func, *args):
349 try:
350 func(*args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000351 except Exception as detail:
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000352 return detail.__class__, str(detail)
Tim Peterse8d09e52006-03-09 01:15:05 +0000353
Zachary Ware9422df02014-06-13 13:44:39 -0500354 @unittest.skip('test disabled')
355 def test_subclass_creation(self):
356 meta = type(Structure)
357 # same as 'class X(Structure): pass'
358 # fails, since we need either a _fields_ or a _abstract_ attribute
359 cls, msg = self.get_except(meta, "X", (Structure,), {})
360 self.assertEqual((cls, msg),
361 (AttributeError, "class must define a '_fields_' attribute"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000362
363 def test_abstract_class(self):
364 class X(Structure):
365 _abstract_ = "something"
366 # try 'X()'
367 cls, msg = self.get_except(eval, "X()", locals())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000368 self.assertEqual((cls, msg), (TypeError, "abstract class"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000369
370 def test_methods(self):
371## class X(Structure):
372## _fields_ = []
373
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200374 self.assertIn("in_dll", dir(type(Structure)))
375 self.assertIn("from_address", dir(type(Structure)))
376 self.assertIn("in_dll", dir(type(Structure)))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000377
Thomas Hellerd7cb1b92009-09-18 19:05:13 +0000378 def test_positional_args(self):
379 # see also http://bugs.python.org/issue5042
380 class W(Structure):
381 _fields_ = [("a", c_int), ("b", c_int)]
382 class X(W):
383 _fields_ = [("c", c_int)]
384 class Y(X):
385 pass
386 class Z(Y):
387 _fields_ = [("d", c_int), ("e", c_int), ("f", c_int)]
388
389 z = Z(1, 2, 3, 4, 5, 6)
390 self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
391 (1, 2, 3, 4, 5, 6))
392 z = Z(1)
393 self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
394 (1, 0, 0, 0, 0, 0))
395 self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7))
396
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000397class PointerMemberTestCase(unittest.TestCase):
398
399 def test(self):
400 # a Structure with a POINTER field
401 class S(Structure):
402 _fields_ = [("array", POINTER(c_int))]
403
404 s = S()
405 # We can assign arrays of the correct type
406 s.array = (c_int * 3)(1, 2, 3)
407 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000408 self.assertEqual(items, [1, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000409
410 # The following are bugs, but are included here because the unittests
411 # also describe the current behaviour.
412 #
413 # This fails with SystemError: bad arg to internal function
414 # or with IndexError (with a patch I have)
415
416 s.array[0] = 42
417
418 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000419 self.assertEqual(items, [42, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000420
421 s.array[0] = 1
422
423## s.array[1] = 42
424
425 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000426 self.assertEqual(items, [1, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000427
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000428 def test_none_to_pointer_fields(self):
429 class S(Structure):
430 _fields_ = [("x", c_int),
431 ("p", POINTER(c_int))]
432
433 s = S()
434 s.x = 12345678
435 s.p = None
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000436 self.assertEqual(s.x, 12345678)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000437
Thomas Wouters89f507f2006-12-13 04:49:30 +0000438class TestRecursiveStructure(unittest.TestCase):
439 def test_contains_itself(self):
440 class Recursive(Structure):
441 pass
442
443 try:
444 Recursive._fields_ = [("next", Recursive)]
Guido van Rossumb940e112007-01-10 16:19:56 +0000445 except AttributeError as details:
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200446 self.assertIn("Structure or union cannot contain itself",
447 str(details))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000448 else:
449 self.fail("Structure or union cannot contain itself")
450
451
452 def test_vice_versa(self):
453 class First(Structure):
454 pass
455 class Second(Structure):
456 pass
457
458 First._fields_ = [("second", Second)]
459
460 try:
461 Second._fields_ = [("first", First)]
Guido van Rossumb940e112007-01-10 16:19:56 +0000462 except AttributeError as details:
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200463 self.assertIn("_fields_ is final", str(details))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000464 else:
465 self.fail("AttributeError not raised")
466
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000467if __name__ == '__main__':
468 unittest.main()