blob: ad13b016e7625798811f4f420fac66bc61c483e8 [file] [log] [blame]
Thomas Hellerb041fda2008-04-30 17:11:46 +00001import unittest
2from ctypes import *
3import re, struct, sys
4
5if sys.byteorder == "little":
6 THIS_ENDIAN = "<"
7 OTHER_ENDIAN = ">"
8else:
9 THIS_ENDIAN = ">"
10 OTHER_ENDIAN = "<"
11
12def normalize(format):
13 # Remove current endian specifier and white space from a format
14 # string
Thomas Heller0261e1e2008-07-15 17:25:07 +000015 if format is None:
16 return ""
Thomas Hellerb041fda2008-04-30 17:11:46 +000017 format = format.replace(OTHER_ENDIAN, THIS_ENDIAN)
18 return re.sub(r"\s", "", format)
19
20class Test(unittest.TestCase):
21
22 def test_native_types(self):
23 for tp, fmt, shape, itemtp in native_types:
24 ob = tp()
25 v = memoryview(ob)
26 try:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000027 self.assertEqual(normalize(v.format), normalize(fmt))
Stefan Krah9a2d99e2012-02-25 12:24:21 +010028 if shape:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000029 self.assertEqual(len(v), shape[0])
Antoine Pitrouc3b39242009-01-03 16:59:18 +000030 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000031 self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
32 self.assertEqual(v.itemsize, sizeof(itemtp))
33 self.assertEqual(v.shape, shape)
Stefan Krah9a2d99e2012-02-25 12:24:21 +010034 # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides
35 # if requested. memoryview currently reconstructs missing
36 # stride information, so this assert will fail.
37 # self.assertEqual(v.strides, ())
38
Thomas Hellerb041fda2008-04-30 17:11:46 +000039 # they are always read/write
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000040 self.assertFalse(v.readonly)
Thomas Hellerb041fda2008-04-30 17:11:46 +000041
42 if v.shape:
43 n = 1
44 for dim in v.shape:
45 n = n * dim
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000046 self.assertEqual(n * v.itemsize, len(v.tobytes()))
Thomas Hellerb041fda2008-04-30 17:11:46 +000047 except:
48 # so that we can see the failing type
49 print(tp)
50 raise
51
52 def test_endian_types(self):
53 for tp, fmt, shape, itemtp in endian_types:
54 ob = tp()
55 v = memoryview(ob)
56 try:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000057 self.assertEqual(v.format, fmt)
Stefan Krah9a2d99e2012-02-25 12:24:21 +010058 if shape:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000059 self.assertEqual(len(v), shape[0])
Antoine Pitrouc3b39242009-01-03 16:59:18 +000060 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000061 self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
62 self.assertEqual(v.itemsize, sizeof(itemtp))
63 self.assertEqual(v.shape, shape)
Stefan Krah9a2d99e2012-02-25 12:24:21 +010064 # XXX Issue #12851
65 # self.assertEqual(v.strides, ())
66
Thomas Hellerb041fda2008-04-30 17:11:46 +000067 # they are always read/write
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000068 self.assertFalse(v.readonly)
Thomas Hellerb041fda2008-04-30 17:11:46 +000069
70 if v.shape:
71 n = 1
72 for dim in v.shape:
73 n = n * dim
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000074 self.assertEqual(n, len(v))
Thomas Hellerb041fda2008-04-30 17:11:46 +000075 except:
76 # so that we can see the failing type
77 print(tp)
78 raise
79
80# define some structure classes
81
82class Point(Structure):
83 _fields_ = [("x", c_long), ("y", c_long)]
84
85class PackedPoint(Structure):
86 _pack_ = 2
87 _fields_ = [("x", c_long), ("y", c_long)]
88
89class Point2(Structure):
90 pass
91Point2._fields_ = [("x", c_long), ("y", c_long)]
92
93class EmptyStruct(Structure):
94 _fields_ = []
95
96class aUnion(Union):
97 _fields_ = [("a", c_int)]
98
Thomas Heller0261e1e2008-07-15 17:25:07 +000099class Incomplete(Structure):
100 pass
101
102class Complete(Structure):
103 pass
104PComplete = POINTER(Complete)
Thomas Hellerf70e1952008-07-15 20:23:33 +0000105Complete._fields_ = [("a", c_long)]
Thomas Heller0261e1e2008-07-15 17:25:07 +0000106
Thomas Hellerb041fda2008-04-30 17:11:46 +0000107################################################################
108#
109# This table contains format strings as they look on little endian
110# machines. The test replaces '<' with '>' on big endian machines.
111#
112native_types = [
113 # type format shape calc itemsize
114
115 ## simple types
116
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100117 (c_char, "<c", (), c_char),
118 (c_byte, "<b", (), c_byte),
119 (c_ubyte, "<B", (), c_ubyte),
120 (c_short, "<h", (), c_short),
121 (c_ushort, "<H", (), c_ushort),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000122
123 # c_int and c_uint may be aliases to c_long
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100124 #(c_int, "<i", (), c_int),
125 #(c_uint, "<I", (), c_uint),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000126
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100127 (c_long, "<l", (), c_long),
128 (c_ulong, "<L", (), c_ulong),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000129
130 # c_longlong and c_ulonglong are aliases on 64-bit platforms
131 #(c_longlong, "<q", None, c_longlong),
132 #(c_ulonglong, "<Q", None, c_ulonglong),
133
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100134 (c_float, "<f", (), c_float),
135 (c_double, "<d", (), c_double),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000136 # c_longdouble may be an alias to c_double
137
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100138 (c_bool, "<?", (), c_bool),
139 (py_object, "<O", (), py_object),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000140
141 ## pointers
142
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100143 (POINTER(c_byte), "&<b", (), POINTER(c_byte)),
144 (POINTER(POINTER(c_long)), "&&<l", (), POINTER(POINTER(c_long))),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000145
146 ## arrays and pointers
147
148 (c_double * 4, "(4)<d", (4,), c_double),
149 (c_float * 4 * 3 * 2, "(2,3,4)<f", (2,3,4), c_float),
150 (POINTER(c_short) * 2, "(2)&<h", (2,), POINTER(c_short)),
151 (POINTER(c_short) * 2 * 3, "(3,2)&<h", (3,2,), POINTER(c_short)),
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100152 (POINTER(c_short * 2), "&(2)<h", (), POINTER(c_short)),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000153
154 ## structures and unions
155
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100156 (Point, "T{<l:x:<l:y:}", (), Point),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000157 # packed structures do not implement the pep
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100158 (PackedPoint, "B", (), PackedPoint),
159 (Point2, "T{<l:x:<l:y:}", (), Point2),
160 (EmptyStruct, "T{}", (), EmptyStruct),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000161 # the pep does't support unions
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100162 (aUnion, "B", (), aUnion),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000163
Thomas Heller0261e1e2008-07-15 17:25:07 +0000164 ## pointer to incomplete structure
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100165 (Incomplete, "B", (), Incomplete),
166 (POINTER(Incomplete), "&B", (), POINTER(Incomplete)),
Thomas Heller0261e1e2008-07-15 17:25:07 +0000167
168 # 'Complete' is a structure that starts incomplete, but is completed after the
169 # pointer type to it has been created.
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100170 (Complete, "T{<l:a:}", (), Complete),
Thomas Heller0261e1e2008-07-15 17:25:07 +0000171 # Unfortunately the pointer format string is not fixed...
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100172 (POINTER(Complete), "&B", (), POINTER(Complete)),
Thomas Heller0261e1e2008-07-15 17:25:07 +0000173
Thomas Hellerb041fda2008-04-30 17:11:46 +0000174 ## other
175
176 # function signatures are not implemented
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100177 (CFUNCTYPE(None), "X{}", (), CFUNCTYPE(None)),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000178
179 ]
180
181class BEPoint(BigEndianStructure):
182 _fields_ = [("x", c_long), ("y", c_long)]
183
184class LEPoint(LittleEndianStructure):
185 _fields_ = [("x", c_long), ("y", c_long)]
186
187################################################################
188#
189# This table contains format strings as they really look, on both big
190# and little endian machines.
191#
192endian_types = [
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100193 (BEPoint, "T{>l:x:>l:y:}", (), BEPoint),
194 (LEPoint, "T{<l:x:<l:y:}", (), LEPoint),
195 (POINTER(BEPoint), "&T{>l:x:>l:y:}", (), POINTER(BEPoint)),
196 (POINTER(LEPoint), "&T{<l:x:<l:y:}", (), POINTER(LEPoint)),
Thomas Hellerb041fda2008-04-30 17:11:46 +0000197 ]
198
199if __name__ == "__main__":
200 unittest.main()