Home | History | Annotate | Download | only in test
      1 from ctypes import *
      2 import unittest
      3 import os
      4 
      5 import ctypes
      6 import _ctypes_test
      7 
      8 class BITS(Structure):
      9     _fields_ = [("A", c_int, 1),
     10                 ("B", c_int, 2),
     11                 ("C", c_int, 3),
     12                 ("D", c_int, 4),
     13                 ("E", c_int, 5),
     14                 ("F", c_int, 6),
     15                 ("G", c_int, 7),
     16                 ("H", c_int, 8),
     17                 ("I", c_int, 9),
     18 
     19                 ("M", c_short, 1),
     20                 ("N", c_short, 2),
     21                 ("O", c_short, 3),
     22                 ("P", c_short, 4),
     23                 ("Q", c_short, 5),
     24                 ("R", c_short, 6),
     25                 ("S", c_short, 7)]
     26 
     27 func = CDLL(_ctypes_test.__file__).unpack_bitfields
     28 func.argtypes = POINTER(BITS), c_char
     29 
     30 ##for n in "ABCDEFGHIMNOPQRS":
     31 ##    print n, hex(getattr(BITS, n).size), getattr(BITS, n).offset
     32 
     33 class C_Test(unittest.TestCase):
     34 
     35     def test_ints(self):
     36         for i in range(512):
     37             for name in "ABCDEFGHI":
     38                 b = BITS()
     39                 setattr(b, name, i)
     40                 self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
     41 
     42     def test_shorts(self):
     43         for i in range(256):
     44             for name in "MNOPQRS":
     45                 b = BITS()
     46                 setattr(b, name, i)
     47                 self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
     48 
     49 signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong)
     50 unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong)
     51 int_types = unsigned_int_types + signed_int_types
     52 
     53 class BitFieldTest(unittest.TestCase):
     54 
     55     def test_longlong(self):
     56         class X(Structure):
     57             _fields_ = [("a", c_longlong, 1),
     58                         ("b", c_longlong, 62),
     59                         ("c", c_longlong, 1)]
     60 
     61         self.assertEqual(sizeof(X), sizeof(c_longlong))
     62         x = X()
     63         x.a, x.b, x.c = -1, 7, -1
     64         self.assertEqual((x.a, x.b, x.c), (-1, 7, -1))
     65 
     66     def test_ulonglong(self):
     67         class X(Structure):
     68             _fields_ = [("a", c_ulonglong, 1),
     69                         ("b", c_ulonglong, 62),
     70                         ("c", c_ulonglong, 1)]
     71 
     72         self.assertEqual(sizeof(X), sizeof(c_longlong))
     73         x = X()
     74         self.assertEqual((x.a, x.b, x.c), (0, 0, 0))
     75         x.a, x.b, x.c = 7, 7, 7
     76         self.assertEqual((x.a, x.b, x.c), (1, 7, 1))
     77 
     78     def test_signed(self):
     79         for c_typ in signed_int_types:
     80             class X(Structure):
     81                 _fields_ = [("dummy", c_typ),
     82                             ("a", c_typ, 3),
     83                             ("b", c_typ, 3),
     84                             ("c", c_typ, 1)]
     85             self.assertEqual(sizeof(X), sizeof(c_typ)*2)
     86 
     87             x = X()
     88             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
     89             x.a = -1
     90             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, -1, 0, 0))
     91             x.a, x.b = 0, -1
     92             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, -1, 0))
     93 
     94 
     95     def test_unsigned(self):
     96         for c_typ in unsigned_int_types:
     97             class X(Structure):
     98                 _fields_ = [("a", c_typ, 3),
     99                             ("b", c_typ, 3),
    100                             ("c", c_typ, 1)]
    101             self.assertEqual(sizeof(X), sizeof(c_typ))
    102 
    103             x = X()
    104             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
    105             x.a = -1
    106             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 7, 0, 0))
    107             x.a, x.b = 0, -1
    108             self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 7, 0))
    109 
    110 
    111     def fail_fields(self, *fields):
    112         return self.get_except(type(Structure), "X", (),
    113                                {"_fields_": fields})
    114 
    115     def test_nonint_types(self):
    116         # bit fields are not allowed on non-integer types.
    117         result = self.fail_fields(("a", c_char_p, 1))
    118         self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p'))
    119 
    120         result = self.fail_fields(("a", c_void_p, 1))
    121         self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p'))
    122 
    123         if c_int != c_long:
    124             result = self.fail_fields(("a", POINTER(c_int), 1))
    125             self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int'))
    126 
    127         result = self.fail_fields(("a", c_char, 1))
    128         self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char'))
    129 
    130         try:
    131             c_wchar
    132         except NameError:
    133             pass
    134         else:
    135             result = self.fail_fields(("a", c_wchar, 1))
    136             self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_wchar'))
    137 
    138         class Dummy(Structure):
    139             _fields_ = []
    140 
    141         result = self.fail_fields(("a", Dummy, 1))
    142         self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy'))
    143 
    144     def test_single_bitfield_size(self):
    145         for c_typ in int_types:
    146             result = self.fail_fields(("a", c_typ, -1))
    147             self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
    148 
    149             result = self.fail_fields(("a", c_typ, 0))
    150             self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
    151 
    152             class X(Structure):
    153                 _fields_ = [("a", c_typ, 1)]
    154             self.assertEqual(sizeof(X), sizeof(c_typ))
    155 
    156             class X(Structure):
    157                 _fields_ = [("a", c_typ, sizeof(c_typ)*8)]
    158             self.assertEqual(sizeof(X), sizeof(c_typ))
    159 
    160             result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1))
    161             self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
    162 
    163     def test_multi_bitfields_size(self):
    164         class X(Structure):
    165             _fields_ = [("a", c_short, 1),
    166                         ("b", c_short, 14),
    167                         ("c", c_short, 1)]
    168         self.assertEqual(sizeof(X), sizeof(c_short))
    169 
    170         class X(Structure):
    171             _fields_ = [("a", c_short, 1),
    172                         ("a1", c_short),
    173                         ("b", c_short, 14),
    174                         ("c", c_short, 1)]
    175         self.assertEqual(sizeof(X), sizeof(c_short)*3)
    176         self.assertEqual(X.a.offset, 0)
    177         self.assertEqual(X.a1.offset, sizeof(c_short))
    178         self.assertEqual(X.b.offset, sizeof(c_short)*2)
    179         self.assertEqual(X.c.offset, sizeof(c_short)*2)
    180 
    181         class X(Structure):
    182             _fields_ = [("a", c_short, 3),
    183                         ("b", c_short, 14),
    184                         ("c", c_short, 14)]
    185         self.assertEqual(sizeof(X), sizeof(c_short)*3)
    186         self.assertEqual(X.a.offset, sizeof(c_short)*0)
    187         self.assertEqual(X.b.offset, sizeof(c_short)*1)
    188         self.assertEqual(X.c.offset, sizeof(c_short)*2)
    189 
    190 
    191     def get_except(self, func, *args, **kw):
    192         try:
    193             func(*args, **kw)
    194         except Exception, detail:
    195             return detail.__class__, str(detail)
    196 
    197     def test_mixed_1(self):
    198         class X(Structure):
    199             _fields_ = [("a", c_byte, 4),
    200                         ("b", c_int, 4)]
    201         if os.name in ("nt", "ce"):
    202             self.assertEqual(sizeof(X), sizeof(c_int)*2)
    203         else:
    204             self.assertEqual(sizeof(X), sizeof(c_int))
    205 
    206     def test_mixed_2(self):
    207         class X(Structure):
    208             _fields_ = [("a", c_byte, 4),
    209                         ("b", c_int, 32)]
    210         self.assertEqual(sizeof(X), sizeof(c_int)*2)
    211 
    212     def test_mixed_3(self):
    213         class X(Structure):
    214             _fields_ = [("a", c_byte, 4),
    215                         ("b", c_ubyte, 4)]
    216         self.assertEqual(sizeof(X), sizeof(c_byte))
    217 
    218     def test_mixed_4(self):
    219         class X(Structure):
    220             _fields_ = [("a", c_short, 4),
    221                         ("b", c_short, 4),
    222                         ("c", c_int, 24),
    223                         ("d", c_short, 4),
    224                         ("e", c_short, 4),
    225                         ("f", c_int, 24)]
    226         # MSVC does NOT combine c_short and c_int into one field, GCC
    227         # does (unless GCC is run with '-mms-bitfields' which
    228         # produces code compatible with MSVC).
    229         if os.name in ("nt", "ce"):
    230             self.assertEqual(sizeof(X), sizeof(c_int) * 4)
    231         else:
    232             self.assertEqual(sizeof(X), sizeof(c_int) * 2)
    233 
    234     def test_anon_bitfields(self):
    235         # anonymous bit-fields gave a strange error message
    236         class X(Structure):
    237             _fields_ = [("a", c_byte, 4),
    238                         ("b", c_ubyte, 4)]
    239         class Y(Structure):
    240             _anonymous_ = ["_"]
    241             _fields_ = [("_", X)]
    242 
    243     @unittest.skipUnless(hasattr(ctypes, "c_uint32"), "c_int32 is required")
    244     def test_uint32(self):
    245         class X(Structure):
    246             _fields_ = [("a", c_uint32, 32)]
    247         x = X()
    248         x.a = 10
    249         self.assertEqual(x.a, 10)
    250         x.a = 0xFDCBA987
    251         self.assertEqual(x.a, 0xFDCBA987)
    252 
    253     @unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required")
    254     def test_uint64(self):
    255         class X(Structure):
    256             _fields_ = [("a", c_uint64, 64)]
    257         x = X()
    258         x.a = 10
    259         self.assertEqual(x.a, 10)
    260         x.a = 0xFEDCBA9876543211
    261         self.assertEqual(x.a, 0xFEDCBA9876543211)
    262 
    263 if __name__ == "__main__":
    264     unittest.main()
    265