1import sys, unittest, struct, math, ctypes 2from binascii import hexlify 3 4from ctypes import * 5 6def bin(s): 7 return hexlify(memoryview(s)).upper() 8 9# Each *simple* type that supports different byte orders has an 10# __ctype_be__ attribute that specifies the same type in BIG ENDIAN 11# byte order, and a __ctype_le__ attribute that is the same type in 12# LITTLE ENDIAN byte order. 13# 14# For Structures and Unions, these types are created on demand. 15 16class Test(unittest.TestCase): 17 @unittest.skip('test disabled') 18 def test_X(self): 19 print >> sys.stderr, sys.byteorder 20 for i in range(32): 21 bits = BITS() 22 setattr(bits, "i%s" % i, 1) 23 dump(bits) 24 25 def test_endian_short(self): 26 if sys.byteorder == "little": 27 self.assertIs(c_short.__ctype_le__, c_short) 28 self.assertIs(c_short.__ctype_be__.__ctype_le__, c_short) 29 else: 30 self.assertIs(c_short.__ctype_be__, c_short) 31 self.assertIs(c_short.__ctype_le__.__ctype_be__, c_short) 32 s = c_short.__ctype_be__(0x1234) 33 self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234") 34 self.assertEqual(bin(s), "1234") 35 self.assertEqual(s.value, 0x1234) 36 37 s = c_short.__ctype_le__(0x1234) 38 self.assertEqual(bin(struct.pack("<h", 0x1234)), "3412") 39 self.assertEqual(bin(s), "3412") 40 self.assertEqual(s.value, 0x1234) 41 42 s = c_ushort.__ctype_be__(0x1234) 43 self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234") 44 self.assertEqual(bin(s), "1234") 45 self.assertEqual(s.value, 0x1234) 46 47 s = c_ushort.__ctype_le__(0x1234) 48 self.assertEqual(bin(struct.pack("<h", 0x1234)), "3412") 49 self.assertEqual(bin(s), "3412") 50 self.assertEqual(s.value, 0x1234) 51 52 def test_endian_int(self): 53 if sys.byteorder == "little": 54 self.assertIs(c_int.__ctype_le__, c_int) 55 self.assertIs(c_int.__ctype_be__.__ctype_le__, c_int) 56 else: 57 self.assertIs(c_int.__ctype_be__, c_int) 58 self.assertIs(c_int.__ctype_le__.__ctype_be__, c_int) 59 60 s = c_int.__ctype_be__(0x12345678) 61 self.assertEqual(bin(struct.pack(">i", 0x12345678)), "12345678") 62 self.assertEqual(bin(s), "12345678") 63 self.assertEqual(s.value, 0x12345678) 64 65 s = c_int.__ctype_le__(0x12345678) 66 self.assertEqual(bin(struct.pack("<i", 0x12345678)), "78563412") 67 self.assertEqual(bin(s), "78563412") 68 self.assertEqual(s.value, 0x12345678) 69 70 s = c_uint.__ctype_be__(0x12345678) 71 self.assertEqual(bin(struct.pack(">I", 0x12345678)), "12345678") 72 self.assertEqual(bin(s), "12345678") 73 self.assertEqual(s.value, 0x12345678) 74 75 s = c_uint.__ctype_le__(0x12345678) 76 self.assertEqual(bin(struct.pack("<I", 0x12345678)), "78563412") 77 self.assertEqual(bin(s), "78563412") 78 self.assertEqual(s.value, 0x12345678) 79 80 def test_endian_longlong(self): 81 if sys.byteorder == "little": 82 self.assertIs(c_longlong.__ctype_le__, c_longlong) 83 self.assertIs(c_longlong.__ctype_be__.__ctype_le__, c_longlong) 84 else: 85 self.assertIs(c_longlong.__ctype_be__, c_longlong) 86 self.assertIs(c_longlong.__ctype_le__.__ctype_be__, c_longlong) 87 88 s = c_longlong.__ctype_be__(0x1234567890ABCDEF) 89 self.assertEqual(bin(struct.pack(">q", 0x1234567890ABCDEF)), "1234567890ABCDEF") 90 self.assertEqual(bin(s), "1234567890ABCDEF") 91 self.assertEqual(s.value, 0x1234567890ABCDEF) 92 93 s = c_longlong.__ctype_le__(0x1234567890ABCDEF) 94 self.assertEqual(bin(struct.pack("<q", 0x1234567890ABCDEF)), "EFCDAB9078563412") 95 self.assertEqual(bin(s), "EFCDAB9078563412") 96 self.assertEqual(s.value, 0x1234567890ABCDEF) 97 98 s = c_ulonglong.__ctype_be__(0x1234567890ABCDEF) 99 self.assertEqual(bin(struct.pack(">Q", 0x1234567890ABCDEF)), "1234567890ABCDEF") 100 self.assertEqual(bin(s), "1234567890ABCDEF") 101 self.assertEqual(s.value, 0x1234567890ABCDEF) 102 103 s = c_ulonglong.__ctype_le__(0x1234567890ABCDEF) 104 self.assertEqual(bin(struct.pack("<Q", 0x1234567890ABCDEF)), "EFCDAB9078563412") 105 self.assertEqual(bin(s), "EFCDAB9078563412") 106 self.assertEqual(s.value, 0x1234567890ABCDEF) 107 108 def test_endian_float(self): 109 if sys.byteorder == "little": 110 self.assertIs(c_float.__ctype_le__, c_float) 111 self.assertIs(c_float.__ctype_be__.__ctype_le__, c_float) 112 else: 113 self.assertIs(c_float.__ctype_be__, c_float) 114 self.assertIs(c_float.__ctype_le__.__ctype_be__, c_float) 115 s = c_float(math.pi) 116 self.assertEqual(bin(struct.pack("f", math.pi)), bin(s)) 117 # Hm, what's the precision of a float compared to a double? 118 self.assertAlmostEqual(s.value, math.pi, 6) 119 s = c_float.__ctype_le__(math.pi) 120 self.assertAlmostEqual(s.value, math.pi, 6) 121 self.assertEqual(bin(struct.pack("<f", math.pi)), bin(s)) 122 s = c_float.__ctype_be__(math.pi) 123 self.assertAlmostEqual(s.value, math.pi, 6) 124 self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s)) 125 126 def test_endian_double(self): 127 if sys.byteorder == "little": 128 self.assertIs(c_double.__ctype_le__, c_double) 129 self.assertIs(c_double.__ctype_be__.__ctype_le__, c_double) 130 else: 131 self.assertIs(c_double.__ctype_be__, c_double) 132 self.assertIs(c_double.__ctype_le__.__ctype_be__, c_double) 133 s = c_double(math.pi) 134 self.assertEqual(s.value, math.pi) 135 self.assertEqual(bin(struct.pack("d", math.pi)), bin(s)) 136 s = c_double.__ctype_le__(math.pi) 137 self.assertEqual(s.value, math.pi) 138 self.assertEqual(bin(struct.pack("<d", math.pi)), bin(s)) 139 s = c_double.__ctype_be__(math.pi) 140 self.assertEqual(s.value, math.pi) 141 self.assertEqual(bin(struct.pack(">d", math.pi)), bin(s)) 142 143 def test_endian_other(self): 144 self.assertIs(c_byte.__ctype_le__, c_byte) 145 self.assertIs(c_byte.__ctype_be__, c_byte) 146 147 self.assertIs(c_ubyte.__ctype_le__, c_ubyte) 148 self.assertIs(c_ubyte.__ctype_be__, c_ubyte) 149 150 self.assertIs(c_char.__ctype_le__, c_char) 151 self.assertIs(c_char.__ctype_be__, c_char) 152 153 def test_struct_fields_1(self): 154 if sys.byteorder == "little": 155 base = BigEndianStructure 156 else: 157 base = LittleEndianStructure 158 159 class T(base): 160 pass 161 _fields_ = [("a", c_ubyte), 162 ("b", c_byte), 163 ("c", c_short), 164 ("d", c_ushort), 165 ("e", c_int), 166 ("f", c_uint), 167 ("g", c_long), 168 ("h", c_ulong), 169 ("i", c_longlong), 170 ("k", c_ulonglong), 171 ("l", c_float), 172 ("m", c_double), 173 ("n", c_char), 174 175 ("b1", c_byte, 3), 176 ("b2", c_byte, 3), 177 ("b3", c_byte, 2), 178 ("a", c_int * 3 * 3 * 3)] 179 T._fields_ = _fields_ 180 181 # these fields do not support different byte order: 182 for typ in c_wchar, c_void_p, POINTER(c_int): 183 _fields_.append(("x", typ)) 184 class T(base): 185 pass 186 self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)]) 187 188 def test_struct_struct(self): 189 # nested structures with different byteorders 190 191 # create nested structures with given byteorders and set memory to data 192 193 for nested, data in ( 194 (BigEndianStructure, b'\0\0\0\1\0\0\0\2'), 195 (LittleEndianStructure, b'\1\0\0\0\2\0\0\0'), 196 ): 197 for parent in ( 198 BigEndianStructure, 199 LittleEndianStructure, 200 Structure, 201 ): 202 class NestedStructure(nested): 203 _fields_ = [("x", c_uint32), 204 ("y", c_uint32)] 205 206 class TestStructure(parent): 207 _fields_ = [("point", NestedStructure)] 208 209 self.assertEqual(len(data), sizeof(TestStructure)) 210 ptr = POINTER(TestStructure) 211 s = cast(data, ptr)[0] 212 del ctypes._pointer_type_cache[TestStructure] 213 self.assertEqual(s.point.x, 1) 214 self.assertEqual(s.point.y, 2) 215 216 def test_struct_fields_2(self): 217 # standard packing in struct uses no alignment. 218 # So, we have to align using pad bytes. 219 # 220 # Unaligned accesses will crash Python (on those platforms that 221 # don't allow it, like sparc solaris). 222 if sys.byteorder == "little": 223 base = BigEndianStructure 224 fmt = ">bxhid" 225 else: 226 base = LittleEndianStructure 227 fmt = "<bxhid" 228 229 class S(base): 230 _fields_ = [("b", c_byte), 231 ("h", c_short), 232 ("i", c_int), 233 ("d", c_double)] 234 235 s1 = S(0x12, 0x1234, 0x12345678, 3.14) 236 s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) 237 self.assertEqual(bin(s1), bin(s2)) 238 239 def test_unaligned_nonnative_struct_fields(self): 240 if sys.byteorder == "little": 241 base = BigEndianStructure 242 fmt = ">b h xi xd" 243 else: 244 base = LittleEndianStructure 245 fmt = "<b h xi xd" 246 247 class S(base): 248 _pack_ = 1 249 _fields_ = [("b", c_byte), 250 251 ("h", c_short), 252 253 ("_1", c_byte), 254 ("i", c_int), 255 256 ("_2", c_byte), 257 ("d", c_double)] 258 259 s1 = S() 260 s1.b = 0x12 261 s1.h = 0x1234 262 s1.i = 0x12345678 263 s1.d = 3.14 264 s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) 265 self.assertEqual(bin(s1), bin(s2)) 266 267 def test_unaligned_native_struct_fields(self): 268 if sys.byteorder == "little": 269 fmt = "<b h xi xd" 270 else: 271 base = LittleEndianStructure 272 fmt = ">b h xi xd" 273 274 class S(Structure): 275 _pack_ = 1 276 _fields_ = [("b", c_byte), 277 278 ("h", c_short), 279 280 ("_1", c_byte), 281 ("i", c_int), 282 283 ("_2", c_byte), 284 ("d", c_double)] 285 286 s1 = S() 287 s1.b = 0x12 288 s1.h = 0x1234 289 s1.i = 0x12345678 290 s1.d = 3.14 291 s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) 292 self.assertEqual(bin(s1), bin(s2)) 293 294if __name__ == "__main__": 295 unittest.main() 296