blob: 3eded7749ed95ea12f76d0be6db9c9c909cfefbe [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
Vinay Sajip3cc58172017-02-22 06:21:17 +00006import _ctypes_test
Thomas Hellerbabddfc2006-03-08 19:56:54 +00007
8class SubclassesTest(unittest.TestCase):
9 def test_subclass(self):
10 class X(Structure):
11 _fields_ = [("a", c_int)]
12
13 class Y(X):
14 _fields_ = [("b", c_int)]
15
16 class Z(X):
17 pass
18
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000019 self.assertEqual(sizeof(X), sizeof(c_int))
20 self.assertEqual(sizeof(Y), sizeof(c_int)*2)
21 self.assertEqual(sizeof(Z), sizeof(c_int))
22 self.assertEqual(X._fields_, [("a", c_int)])
23 self.assertEqual(Y._fields_, [("b", c_int)])
24 self.assertEqual(Z._fields_, [("a", c_int)])
Thomas Hellerbabddfc2006-03-08 19:56:54 +000025
26 def test_subclass_delayed(self):
27 class X(Structure):
28 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000029 self.assertEqual(sizeof(X), 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000030 X._fields_ = [("a", c_int)]
31
32 class Y(X):
33 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000034 self.assertEqual(sizeof(Y), sizeof(X))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000035 Y._fields_ = [("b", c_int)]
36
37 class Z(X):
38 pass
39
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000040 self.assertEqual(sizeof(X), sizeof(c_int))
41 self.assertEqual(sizeof(Y), sizeof(c_int)*2)
42 self.assertEqual(sizeof(Z), sizeof(c_int))
43 self.assertEqual(X._fields_, [("a", c_int)])
44 self.assertEqual(Y._fields_, [("b", c_int)])
45 self.assertEqual(Z._fields_, [("a", c_int)])
Thomas Hellerbabddfc2006-03-08 19:56:54 +000046
47class StructureTestCase(unittest.TestCase):
48 formats = {"c": c_char,
49 "b": c_byte,
50 "B": c_ubyte,
51 "h": c_short,
52 "H": c_ushort,
53 "i": c_int,
54 "I": c_uint,
55 "l": c_long,
56 "L": c_ulong,
57 "q": c_longlong,
58 "Q": c_ulonglong,
59 "f": c_float,
60 "d": c_double,
61 }
Tim Peterse8d09e52006-03-09 01:15:05 +000062
Thomas Hellerbabddfc2006-03-08 19:56:54 +000063 def test_simple_structs(self):
64 for code, tp in self.formats.items():
65 class X(Structure):
66 _fields_ = [("x", c_char),
67 ("y", tp)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000068 self.assertEqual((sizeof(X), code),
Thomas Hellerbabddfc2006-03-08 19:56:54 +000069 (calcsize("c%c0%c" % (code, code)), code))
70
71 def test_unions(self):
72 for code, tp in self.formats.items():
73 class X(Union):
74 _fields_ = [("x", c_char),
75 ("y", tp)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000076 self.assertEqual((sizeof(X), code),
Thomas Hellerbabddfc2006-03-08 19:56:54 +000077 (calcsize("%c" % (code)), code))
78
79 def test_struct_alignment(self):
80 class X(Structure):
81 _fields_ = [("x", c_char * 3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000082 self.assertEqual(alignment(X), calcsize("s"))
83 self.assertEqual(sizeof(X), calcsize("3s"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000084
85 class Y(Structure):
86 _fields_ = [("x", c_char * 3),
87 ("y", c_int)]
Benjamin Petersonfda33552014-03-16 10:07:26 +010088 self.assertEqual(alignment(Y), alignment(c_int))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000089 self.assertEqual(sizeof(Y), calcsize("3si"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000090
91 class SI(Structure):
92 _fields_ = [("a", X),
93 ("b", Y)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000094 self.assertEqual(alignment(SI), max(alignment(Y), alignment(X)))
95 self.assertEqual(sizeof(SI), calcsize("3s0i 3si 0i"))
Tim Peterse8d09e52006-03-09 01:15:05 +000096
Thomas Hellerbabddfc2006-03-08 19:56:54 +000097 class IS(Structure):
98 _fields_ = [("b", Y),
99 ("a", X)]
100
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000101 self.assertEqual(alignment(SI), max(alignment(X), alignment(Y)))
102 self.assertEqual(sizeof(IS), calcsize("3si 3s 0i"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000103
104 class XX(Structure):
105 _fields_ = [("a", X),
106 ("b", X)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000107 self.assertEqual(alignment(XX), alignment(X))
108 self.assertEqual(sizeof(XX), calcsize("3s 3s 0s"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000109
Martin Pantereb995702016-07-28 01:11:04 +0000110 def test_empty(self):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000111 # I had problems with these
112 #
Ezio Melottib5bc3532013-08-17 16:11:40 +0300113 # Although these are pathological cases: Empty Structures!
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000114 class X(Structure):
115 _fields_ = []
116
117 class Y(Union):
118 _fields_ = []
119
120 # Is this really the correct alignment, or should it be 0?
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000121 self.assertTrue(alignment(X) == alignment(Y) == 1)
122 self.assertTrue(sizeof(X) == sizeof(Y) == 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000123
124 class XX(Structure):
125 _fields_ = [("a", X),
126 ("b", X)]
127
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000128 self.assertEqual(alignment(XX), 1)
129 self.assertEqual(sizeof(XX), 0)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000130
131 def test_fields(self):
132 # test the offset and size attributes of Structure/Unoin fields.
133 class X(Structure):
134 _fields_ = [("x", c_int),
135 ("y", c_char)]
136
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000137 self.assertEqual(X.x.offset, 0)
138 self.assertEqual(X.x.size, sizeof(c_int))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000139
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000140 self.assertEqual(X.y.offset, sizeof(c_int))
141 self.assertEqual(X.y.size, sizeof(c_char))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000142
143 # readonly
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000144 self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
145 self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000146
147 class X(Union):
148 _fields_ = [("x", c_int),
149 ("y", c_char)]
150
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000151 self.assertEqual(X.x.offset, 0)
152 self.assertEqual(X.x.size, sizeof(c_int))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000153
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000154 self.assertEqual(X.y.offset, 0)
155 self.assertEqual(X.y.size, sizeof(c_char))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000156
157 # readonly
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000158 self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
159 self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000160
161 # XXX Should we check nested data types also?
162 # offset is always relative to the class...
163
164 def test_packed(self):
165 class X(Structure):
166 _fields_ = [("a", c_byte),
167 ("b", c_longlong)]
168 _pack_ = 1
169
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000170 self.assertEqual(sizeof(X), 9)
171 self.assertEqual(X.b.offset, 1)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000172
173 class X(Structure):
174 _fields_ = [("a", c_byte),
175 ("b", c_longlong)]
176 _pack_ = 2
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000177 self.assertEqual(sizeof(X), 10)
178 self.assertEqual(X.b.offset, 2)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000179
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000180 import struct
181 longlong_size = struct.calcsize("q")
182 longlong_align = struct.calcsize("bq") - longlong_size
183
184 class X(Structure):
185 _fields_ = [("a", c_byte),
186 ("b", c_longlong)]
Benjamin Petersonfda33552014-03-16 10:07:26 +0100187 _pack_ = 4
188 self.assertEqual(sizeof(X), min(4, longlong_align) + longlong_size)
189 self.assertEqual(X.b.offset, min(4, longlong_align))
190
191 class X(Structure):
192 _fields_ = [("a", c_byte),
193 ("b", c_longlong)]
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000194 _pack_ = 8
195
Benjamin Petersonfda33552014-03-16 10:07:26 +0100196 self.assertEqual(sizeof(X), min(8, longlong_align) + longlong_size)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000197 self.assertEqual(X.b.offset, min(8, longlong_align))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000198
199
200 d = {"_fields_": [("a", "b"),
201 ("b", "q")],
202 "_pack_": -1}
203 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
204
Serhiy Storchaka441d30f2013-01-19 12:26:26 +0200205 # Issue 15989
206 d = {"_fields_": [("a", c_byte)],
207 "_pack_": _testcapi.INT_MAX + 1}
208 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
209 d = {"_fields_": [("a", c_byte)],
210 "_pack_": _testcapi.UINT_MAX + 2}
211 self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
212
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000213 def test_initializers(self):
214 class Person(Structure):
215 _fields_ = [("name", c_char*6),
216 ("age", c_int)]
217
218 self.assertRaises(TypeError, Person, 42)
Victor Stinner42746df2010-07-27 23:36:41 +0000219 self.assertRaises(ValueError, Person, b"asldkjaslkdjaslkdj")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000220 self.assertRaises(TypeError, Person, "Name", "HI")
221
222 # short enough
Victor Stinner42746df2010-07-27 23:36:41 +0000223 self.assertEqual(Person(b"12345", 5).name, b"12345")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000224 # exact fit
Victor Stinner42746df2010-07-27 23:36:41 +0000225 self.assertEqual(Person(b"123456", 5).name, b"123456")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000226 # too long
Victor Stinner42746df2010-07-27 23:36:41 +0000227 self.assertRaises(ValueError, Person, b"1234567", 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000228
Thomas Hellerff721222008-01-17 18:46:55 +0000229 def test_conflicting_initializers(self):
230 class POINT(Structure):
Serhiy Storchaka886a5f32016-06-18 09:58:24 +0300231 _fields_ = [("phi", c_float), ("rho", c_float)]
Thomas Hellerff721222008-01-17 18:46:55 +0000232 # conflicting positional and keyword args
Serhiy Storchaka886a5f32016-06-18 09:58:24 +0300233 self.assertRaisesRegex(TypeError, "phi", POINT, 2, 3, phi=4)
234 self.assertRaisesRegex(TypeError, "rho", POINT, 2, 3, rho=4)
Thomas Hellerff721222008-01-17 18:46:55 +0000235
236 # too many initializers
237 self.assertRaises(TypeError, POINT, 2, 3, 4)
Tim Peterse8d09e52006-03-09 01:15:05 +0000238
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000239 def test_keyword_initializers(self):
240 class POINT(Structure):
241 _fields_ = [("x", c_int), ("y", c_int)]
242 pt = POINT(1, 2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000243 self.assertEqual((pt.x, pt.y), (1, 2))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000244
245 pt = POINT(y=2, x=1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000246 self.assertEqual((pt.x, pt.y), (1, 2))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000247
248 def test_invalid_field_types(self):
249 class POINT(Structure):
250 pass
251 self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
252
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200253 def test_invalid_name(self):
254 # field name must be string
255 def declare_with_name(name):
256 class S(Structure):
257 _fields_ = [(name, c_int)]
258
259 self.assertRaises(TypeError, declare_with_name, b"x")
260
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000261 def test_intarray_fields(self):
262 class SomeInts(Structure):
263 _fields_ = [("a", c_int * 4)]
264
265 # can use tuple to initialize array (but not list!)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000266 self.assertEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
267 self.assertEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
268 self.assertEqual(SomeInts((1, 2)).a[::-1], [0, 0, 2, 1])
269 self.assertEqual(SomeInts((1, 2)).a[::2], [1, 0])
270 self.assertEqual(SomeInts((1, 2)).a[1:5:6], [2])
271 self.assertEqual(SomeInts((1, 2)).a[6:4:-1], [])
272 self.assertEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
273 self.assertEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000274 # too long
275 # XXX Should raise ValueError?, not RuntimeError
276 self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
277
278 def test_nested_initializers(self):
279 # test initializing nested structures
280 class Phone(Structure):
281 _fields_ = [("areacode", c_char*6),
282 ("number", c_char*12)]
283
284 class Person(Structure):
285 _fields_ = [("name", c_char * 12),
286 ("phone", Phone),
287 ("age", c_int)]
288
Victor Stinner42746df2010-07-27 23:36:41 +0000289 p = Person(b"Someone", (b"1234", b"5678"), 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000290
Victor Stinnerda0eca42010-06-11 21:50:30 +0000291 self.assertEqual(p.name, b"Someone")
292 self.assertEqual(p.phone.areacode, b"1234")
293 self.assertEqual(p.phone.number, b"5678")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000294 self.assertEqual(p.age, 5)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000295
Zachary Ware9422df02014-06-13 13:44:39 -0500296 @need_symbol('c_wchar')
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000297 def test_structures_with_wchar(self):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000298 class PersonW(Structure):
299 _fields_ = [("name", c_wchar * 12),
300 ("age", c_int)]
301
Victor Stinner42746df2010-07-27 23:36:41 +0000302 p = PersonW("Someone \xe9")
303 self.assertEqual(p.name, "Someone \xe9")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000304
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000305 self.assertEqual(PersonW("1234567890").name, "1234567890")
306 self.assertEqual(PersonW("12345678901").name, "12345678901")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000307 # exact fit
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000308 self.assertEqual(PersonW("123456789012").name, "123456789012")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000309 #too long
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000310 self.assertRaises(ValueError, PersonW, "1234567890123")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000311
312 def test_init_errors(self):
313 class Phone(Structure):
314 _fields_ = [("areacode", c_char*6),
315 ("number", c_char*12)]
316
317 class Person(Structure):
318 _fields_ = [("name", c_char * 12),
319 ("phone", Phone),
320 ("age", c_int)]
321
Victor Stinner42746df2010-07-27 23:36:41 +0000322 cls, msg = self.get_except(Person, b"Someone", (1, 2))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000323 self.assertEqual(cls, RuntimeError)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700324 self.assertEqual(msg,
325 "(Phone) <class 'TypeError'>: "
326 "expected bytes, int found")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000327
Victor Stinner42746df2010-07-27 23:36:41 +0000328 cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c"))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000329 self.assertEqual(cls, RuntimeError)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700330 self.assertEqual(msg,
331 "(Phone) <class 'TypeError'>: too many initializers")
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000332
Meador Inge1efb33a2011-10-03 21:44:22 -0500333 def test_huge_field_name(self):
334 # issue12881: segfault with large structure field names
335 def create_class(length):
336 class S(Structure):
337 _fields_ = [('x' * length, c_int)]
338
339 for length in [10 ** i for i in range(0, 8)]:
340 try:
341 create_class(length)
342 except MemoryError:
343 # MemoryErrors are OK, we just don't want to segfault
344 pass
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000345
346 def get_except(self, func, *args):
347 try:
348 func(*args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000349 except Exception as detail:
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000350 return detail.__class__, str(detail)
Tim Peterse8d09e52006-03-09 01:15:05 +0000351
Zachary Ware9422df02014-06-13 13:44:39 -0500352 @unittest.skip('test disabled')
353 def test_subclass_creation(self):
354 meta = type(Structure)
355 # same as 'class X(Structure): pass'
356 # fails, since we need either a _fields_ or a _abstract_ attribute
357 cls, msg = self.get_except(meta, "X", (Structure,), {})
358 self.assertEqual((cls, msg),
359 (AttributeError, "class must define a '_fields_' attribute"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000360
361 def test_abstract_class(self):
362 class X(Structure):
363 _abstract_ = "something"
364 # try 'X()'
365 cls, msg = self.get_except(eval, "X()", locals())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000366 self.assertEqual((cls, msg), (TypeError, "abstract class"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000367
368 def test_methods(self):
369## class X(Structure):
370## _fields_ = []
371
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200372 self.assertIn("in_dll", dir(type(Structure)))
373 self.assertIn("from_address", dir(type(Structure)))
374 self.assertIn("in_dll", dir(type(Structure)))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000375
Thomas Hellerd7cb1b92009-09-18 19:05:13 +0000376 def test_positional_args(self):
377 # see also http://bugs.python.org/issue5042
378 class W(Structure):
379 _fields_ = [("a", c_int), ("b", c_int)]
380 class X(W):
381 _fields_ = [("c", c_int)]
382 class Y(X):
383 pass
384 class Z(Y):
385 _fields_ = [("d", c_int), ("e", c_int), ("f", c_int)]
386
387 z = Z(1, 2, 3, 4, 5, 6)
388 self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
389 (1, 2, 3, 4, 5, 6))
390 z = Z(1)
391 self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
392 (1, 0, 0, 0, 0, 0))
393 self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7))
394
Vinay Sajip3cc58172017-02-22 06:21:17 +0000395 def test_pass_by_value(self):
396 # This should mirror the structure in Modules/_ctypes/_ctypes_test.c
397 class X(Structure):
398 _fields_ = [
399 ('first', c_ulong),
400 ('second', c_ulong),
401 ('third', c_ulong),
402 ]
403
404 s = X()
405 s.first = 0xdeadbeef
406 s.second = 0xcafebabe
407 s.third = 0x0bad1dea
408 dll = CDLL(_ctypes_test.__file__)
409 func = dll._testfunc_large_struct_update_value
410 func.argtypes = (X,)
411 func.restype = None
412 func(s)
413 self.assertEqual(s.first, 0xdeadbeef)
414 self.assertEqual(s.second, 0xcafebabe)
415 self.assertEqual(s.third, 0x0bad1dea)
416
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000417class PointerMemberTestCase(unittest.TestCase):
418
419 def test(self):
420 # a Structure with a POINTER field
421 class S(Structure):
422 _fields_ = [("array", POINTER(c_int))]
423
424 s = S()
425 # We can assign arrays of the correct type
426 s.array = (c_int * 3)(1, 2, 3)
427 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000428 self.assertEqual(items, [1, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000429
430 # The following are bugs, but are included here because the unittests
431 # also describe the current behaviour.
432 #
433 # This fails with SystemError: bad arg to internal function
434 # or with IndexError (with a patch I have)
435
436 s.array[0] = 42
437
438 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000439 self.assertEqual(items, [42, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000440
441 s.array[0] = 1
442
443## s.array[1] = 42
444
445 items = [s.array[i] for i in range(3)]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000446 self.assertEqual(items, [1, 2, 3])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000447
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000448 def test_none_to_pointer_fields(self):
449 class S(Structure):
450 _fields_ = [("x", c_int),
451 ("p", POINTER(c_int))]
452
453 s = S()
454 s.x = 12345678
455 s.p = None
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000456 self.assertEqual(s.x, 12345678)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000457
Thomas Wouters89f507f2006-12-13 04:49:30 +0000458class TestRecursiveStructure(unittest.TestCase):
459 def test_contains_itself(self):
460 class Recursive(Structure):
461 pass
462
463 try:
464 Recursive._fields_ = [("next", Recursive)]
Guido van Rossumb940e112007-01-10 16:19:56 +0000465 except AttributeError as details:
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200466 self.assertIn("Structure or union cannot contain itself",
467 str(details))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000468 else:
469 self.fail("Structure or union cannot contain itself")
470
471
472 def test_vice_versa(self):
473 class First(Structure):
474 pass
475 class Second(Structure):
476 pass
477
478 First._fields_ = [("second", Second)]
479
480 try:
481 Second._fields_ = [("first", First)]
Guido van Rossumb940e112007-01-10 16:19:56 +0000482 except AttributeError as details:
Serhiy Storchaka7c5e24f2013-11-16 23:51:26 +0200483 self.assertIn("_fields_ is final", str(details))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000484 else:
485 self.fail("AttributeError not raised")
486
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000487if __name__ == '__main__':
488 unittest.main()