PageRenderTime 282ms CodeModel.GetById 141ms app.highlight 20ms RepoModel.GetById 80ms app.codeStats 1ms

/Lib/ctypes/test/test_pep3118.py

http://unladen-swallow.googlecode.com/
Python | 211 lines | 201 code | 3 blank | 7 comment | 5 complexity | ed44c97ec50a050d80fe3ae64d43f7d8 MD5 | raw file
  1import 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
 12class memoryview(object):
 13    # This class creates a memoryview - like object from data returned
 14    # by the private _ctypes._buffer_info() function, just enough for
 15    # these tests.
 16    #
 17    # It can be removed when the py3k memoryview object is backported.
 18    def __init__(self, ob):
 19        from _ctypes import _buffer_info
 20        self.format, self.ndim, self.shape = _buffer_info(ob)
 21        if self.shape == ():
 22            self.shape = None
 23            self.itemsize = sizeof(ob)
 24        else:
 25            size = sizeof(ob)
 26            for dim in self.shape:
 27                size /= dim
 28            self.itemsize = size
 29        self.strides = None
 30        self.readonly = False
 31        self.size = sizeof(ob)
 32
 33def normalize(format):
 34    # Remove current endian specifier and white space from a format
 35    # string
 36    if format is None:
 37        return ""
 38    format = format.replace(OTHER_ENDIAN, THIS_ENDIAN)
 39    return re.sub(r"\s", "", format)
 40
 41class Test(unittest.TestCase):
 42
 43    def test_native_types(self):
 44        for tp, fmt, shape, itemtp in native_types:
 45            ob = tp()
 46            v = memoryview(ob)
 47            try:
 48                self.failUnlessEqual(normalize(v.format), normalize(fmt))
 49                self.failUnlessEqual(v.size, sizeof(ob))
 50                self.failUnlessEqual(v.itemsize, sizeof(itemtp))
 51                self.failUnlessEqual(v.shape, shape)
 52                # ctypes object always have a non-strided memory block
 53                self.failUnlessEqual(v.strides, None)
 54                # they are always read/write
 55                self.failIf(v.readonly)
 56
 57                if v.shape:
 58                    n = 1
 59                    for dim in v.shape:
 60                        n = n * dim
 61                    self.failUnlessEqual(v.itemsize * n, v.size)
 62            except:
 63                # so that we can see the failing type
 64                print(tp)
 65                raise
 66
 67    def test_endian_types(self):
 68        for tp, fmt, shape, itemtp in endian_types:
 69            ob = tp()
 70            v = memoryview(ob)
 71            try:
 72                self.failUnlessEqual(v.format, fmt)
 73                self.failUnlessEqual(v.size, sizeof(ob))
 74                self.failUnlessEqual(v.itemsize, sizeof(itemtp))
 75                self.failUnlessEqual(v.shape, shape)
 76                # ctypes object always have a non-strided memory block
 77                self.failUnlessEqual(v.strides, None)
 78                # they are always read/write
 79                self.failIf(v.readonly)
 80
 81                if v.shape:
 82                    n = 1
 83                    for dim in v.shape:
 84                        n = n * dim
 85                    self.failUnlessEqual(v.itemsize * n, v.size)
 86            except:
 87                # so that we can see the failing type
 88                print(tp)
 89                raise
 90
 91# define some structure classes
 92
 93class Point(Structure):
 94    _fields_ = [("x", c_long), ("y", c_long)]
 95
 96class PackedPoint(Structure):
 97    _pack_ = 2
 98    _fields_ = [("x", c_long), ("y", c_long)]
 99
100class Point2(Structure):
101    pass
102Point2._fields_ = [("x", c_long), ("y", c_long)]
103
104class EmptyStruct(Structure):
105    _fields_ = []
106
107class aUnion(Union):
108    _fields_ = [("a", c_int)]
109
110class Incomplete(Structure):
111    pass
112
113class Complete(Structure):
114    pass
115PComplete = POINTER(Complete)
116Complete._fields_ = [("a", c_long)]
117
118################################################################
119#
120# This table contains format strings as they look on little endian
121# machines.  The test replaces '<' with '>' on big endian machines.
122#
123native_types = [
124    # type                      format                  shape           calc itemsize
125
126    ## simple types
127
128    (c_char,                    "<c",                   None,           c_char),
129    (c_byte,                    "<b",                   None,           c_byte),
130    (c_ubyte,                   "<B",                   None,           c_ubyte),
131    (c_short,                   "<h",                   None,           c_short),
132    (c_ushort,                  "<H",                   None,           c_ushort),
133
134    # c_int and c_uint may be aliases to c_long
135    #(c_int,                     "<i",                   None,           c_int),
136    #(c_uint,                    "<I",                   None,           c_uint),
137
138    (c_long,                    "<l",                   None,           c_long),
139    (c_ulong,                   "<L",                   None,           c_ulong),
140
141    # c_longlong and c_ulonglong are aliases on 64-bit platforms
142    #(c_longlong,                "<q",                   None,           c_longlong),
143    #(c_ulonglong,               "<Q",                   None,           c_ulonglong),
144
145    (c_float,                   "<f",                   None,           c_float),
146    (c_double,                  "<d",                   None,           c_double),
147    # c_longdouble may be an alias to c_double
148
149    (c_bool,                    "<?",                   None,           c_bool),
150    (py_object,                 "<O",                   None,           py_object),
151
152    ## pointers
153
154    (POINTER(c_byte),           "&<b",                  None,           POINTER(c_byte)),
155    (POINTER(POINTER(c_long)),  "&&<l",                 None,           POINTER(POINTER(c_long))),
156
157    ## arrays and pointers
158
159    (c_double * 4,              "(4)<d",                (4,),           c_double),
160    (c_float * 4 * 3 * 2,       "(2,3,4)<f",            (2,3,4),        c_float),
161    (POINTER(c_short) * 2,      "(2)&<h",               (2,),           POINTER(c_short)),
162    (POINTER(c_short) * 2 * 3,  "(3,2)&<h",             (3,2,),         POINTER(c_short)),
163    (POINTER(c_short * 2),      "&(2)<h",               None,           POINTER(c_short)),
164
165    ## structures and unions
166
167    (Point,                     "T{<l:x:<l:y:}",        None,           Point),
168    # packed structures do not implement the pep
169    (PackedPoint,               "B",                    None,           PackedPoint),
170    (Point2,                    "T{<l:x:<l:y:}",        None,           Point2),
171    (EmptyStruct,               "T{}",                  None,           EmptyStruct),
172    # the pep does't support unions
173    (aUnion,                    "B",                    None,           aUnion),
174
175    ## pointer to incomplete structure
176    (Incomplete,                "B",                    None,           Incomplete),
177    (POINTER(Incomplete),       "&B",                   None,           POINTER(Incomplete)),
178
179    # 'Complete' is a structure that starts incomplete, but is completed after the
180    # pointer type to it has been created.
181    (Complete,                  "T{<l:a:}",             None,           Complete),
182    # Unfortunately the pointer format string is not fixed...
183    (POINTER(Complete),         "&B",                   None,           POINTER(Complete)),
184
185    ## other
186
187    # function signatures are not implemented
188    (CFUNCTYPE(None),           "X{}",                  None,           CFUNCTYPE(None)),
189
190    ]
191
192class BEPoint(BigEndianStructure):
193    _fields_ = [("x", c_long), ("y", c_long)]
194
195class LEPoint(LittleEndianStructure):
196    _fields_ = [("x", c_long), ("y", c_long)]
197
198################################################################
199#
200# This table contains format strings as they really look, on both big
201# and little endian machines.
202#
203endian_types = [
204    (BEPoint,                   "T{>l:x:>l:y:}",        None,           BEPoint),
205    (LEPoint,                   "T{<l:x:<l:y:}",        None,           LEPoint),
206    (POINTER(BEPoint),          "&T{>l:x:>l:y:}",       None,           POINTER(BEPoint)),
207    (POINTER(LEPoint),          "&T{<l:x:<l:y:}",       None,           POINTER(LEPoint)),
208    ]
209
210if __name__ == "__main__":
211    unittest.main()