test_struct.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. import os
  2. import array
  3. import unittest
  4. import struct
  5. import inspect
  6. from test import test_support as support
  7. from test.test_support import (check_warnings, check_py3k_warnings)
  8. import sys
  9. ISBIGENDIAN = sys.byteorder == "big"
  10. IS32BIT = sys.maxsize == 0x7fffffff
  11. integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'
  12. testmod_filename = os.path.splitext(__file__)[0] + '.py'
  13. # Native 'q' packing isn't available on systems that don't have the C
  14. # long long type.
  15. try:
  16. struct.pack('q', 5)
  17. except struct.error:
  18. HAVE_LONG_LONG = False
  19. else:
  20. HAVE_LONG_LONG = True
  21. def string_reverse(s):
  22. return "".join(reversed(s))
  23. def bigendian_to_native(value):
  24. if ISBIGENDIAN:
  25. return value
  26. else:
  27. return string_reverse(value)
  28. class StructTest(unittest.TestCase):
  29. def check_float_coerce(self, format, number):
  30. # SF bug 1530559. struct.pack raises TypeError where it used
  31. # to convert.
  32. with check_warnings((".*integer argument expected, got float",
  33. DeprecationWarning)) as w:
  34. got = struct.pack(format, number)
  35. lineno = inspect.currentframe().f_lineno - 1
  36. self.assertEqual(w.filename, testmod_filename)
  37. self.assertEqual(w.lineno, lineno)
  38. self.assertEqual(len(w.warnings), 1)
  39. expected = struct.pack(format, int(number))
  40. self.assertEqual(got, expected)
  41. def test_isbigendian(self):
  42. self.assertEqual((struct.pack('=i', 1)[0] == chr(0)), ISBIGENDIAN)
  43. def test_consistence(self):
  44. self.assertRaises(struct.error, struct.calcsize, 'Z')
  45. sz = struct.calcsize('i')
  46. self.assertEqual(sz * 3, struct.calcsize('iii'))
  47. fmt = 'cbxxxxxxhhhhiillffd?'
  48. fmt3 = '3c3b18x12h6i6l6f3d3?'
  49. sz = struct.calcsize(fmt)
  50. sz3 = struct.calcsize(fmt3)
  51. self.assertEqual(sz * 3, sz3)
  52. self.assertRaises(struct.error, struct.pack, 'iii', 3)
  53. self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
  54. self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo')
  55. self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo')
  56. self.assertRaises(struct.error, struct.unpack, 'd', 'flap')
  57. s = struct.pack('ii', 1, 2)
  58. self.assertRaises(struct.error, struct.unpack, 'iii', s)
  59. self.assertRaises(struct.error, struct.unpack, 'i', s)
  60. def test_transitiveness(self):
  61. c = 'a'
  62. b = 1
  63. h = 255
  64. i = 65535
  65. l = 65536
  66. f = 3.1415
  67. d = 3.1415
  68. t = True
  69. for prefix in ('', '@', '<', '>', '=', '!'):
  70. for format in ('xcbhilfd?', 'xcBHILfd?'):
  71. format = prefix + format
  72. s = struct.pack(format, c, b, h, i, l, f, d, t)
  73. cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
  74. self.assertEqual(cp, c)
  75. self.assertEqual(bp, b)
  76. self.assertEqual(hp, h)
  77. self.assertEqual(ip, i)
  78. self.assertEqual(lp, l)
  79. self.assertEqual(int(100 * fp), int(100 * f))
  80. self.assertEqual(int(100 * dp), int(100 * d))
  81. self.assertEqual(tp, t)
  82. def test_new_features(self):
  83. # Test some of the new features in detail
  84. # (format, argument, big-endian result, little-endian result, asymmetric)
  85. tests = [
  86. ('c', 'a', 'a', 'a', 0),
  87. ('xc', 'a', '\0a', '\0a', 0),
  88. ('cx', 'a', 'a\0', 'a\0', 0),
  89. ('s', 'a', 'a', 'a', 0),
  90. ('0s', 'helloworld', '', '', 1),
  91. ('1s', 'helloworld', 'h', 'h', 1),
  92. ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
  93. ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
  94. ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
  95. ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
  96. ('b', 7, '\7', '\7', 0),
  97. ('b', -7, '\371', '\371', 0),
  98. ('B', 7, '\7', '\7', 0),
  99. ('B', 249, '\371', '\371', 0),
  100. ('h', 700, '\002\274', '\274\002', 0),
  101. ('h', -700, '\375D', 'D\375', 0),
  102. ('H', 700, '\002\274', '\274\002', 0),
  103. ('H', 0x10000-700, '\375D', 'D\375', 0),
  104. ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
  105. ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
  106. ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
  107. ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
  108. ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
  109. ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
  110. ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
  111. ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
  112. ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
  113. ('d', 2.0, '@\000\000\000\000\000\000\000',
  114. '\000\000\000\000\000\000\000@', 0),
  115. ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
  116. ('d', -2.0, '\300\000\000\000\000\000\000\000',
  117. '\000\000\000\000\000\000\000\300', 0),
  118. ('?', 0, '\0', '\0', 0),
  119. ('?', 3, '\1', '\1', 1),
  120. ('?', True, '\1', '\1', 0),
  121. ('?', [], '\0', '\0', 1),
  122. ('?', (1,), '\1', '\1', 1),
  123. ]
  124. for fmt, arg, big, lil, asy in tests:
  125. for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
  126. ('='+fmt, ISBIGENDIAN and big or lil)]:
  127. res = struct.pack(xfmt, arg)
  128. self.assertEqual(res, exp)
  129. self.assertEqual(struct.calcsize(xfmt), len(res))
  130. rev = struct.unpack(xfmt, res)[0]
  131. if rev != arg:
  132. self.assertTrue(asy)
  133. def test_calcsize(self):
  134. expected_size = {
  135. 'b': 1, 'B': 1,
  136. 'h': 2, 'H': 2,
  137. 'i': 4, 'I': 4,
  138. 'l': 4, 'L': 4,
  139. 'q': 8, 'Q': 8,
  140. }
  141. # standard integer sizes
  142. for code in integer_codes:
  143. for byteorder in ('=', '<', '>', '!'):
  144. format = byteorder+code
  145. size = struct.calcsize(format)
  146. self.assertEqual(size, expected_size[code])
  147. # native integer sizes, except 'q' and 'Q'
  148. for format_pair in ('bB', 'hH', 'iI', 'lL'):
  149. for byteorder in ['', '@']:
  150. signed_size = struct.calcsize(byteorder + format_pair[0])
  151. unsigned_size = struct.calcsize(byteorder + format_pair[1])
  152. self.assertEqual(signed_size, unsigned_size)
  153. # bounds for native integer sizes
  154. self.assertEqual(struct.calcsize('b'), 1)
  155. self.assertLessEqual(2, struct.calcsize('h'))
  156. self.assertLessEqual(4, struct.calcsize('l'))
  157. self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i'))
  158. self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l'))
  159. # tests for native 'q' and 'Q' when applicable
  160. if HAVE_LONG_LONG:
  161. self.assertEqual(struct.calcsize('q'), struct.calcsize('Q'))
  162. self.assertLessEqual(8, struct.calcsize('q'))
  163. self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q'))
  164. def test_integers(self):
  165. # Integer tests (bBhHiIlLqQ).
  166. import binascii
  167. class IntTester(unittest.TestCase):
  168. def __init__(self, format):
  169. super(IntTester, self).__init__(methodName='test_one')
  170. self.format = format
  171. self.code = format[-1]
  172. self.direction = format[:-1]
  173. if not self.direction in ('', '@', '=', '<', '>', '!'):
  174. raise ValueError("unrecognized packing direction: %s" %
  175. self.direction)
  176. self.bytesize = struct.calcsize(format)
  177. self.bitsize = self.bytesize * 8
  178. if self.code in tuple('bhilq'):
  179. self.signed = True
  180. self.min_value = -(2L**(self.bitsize-1))
  181. self.max_value = 2L**(self.bitsize-1) - 1
  182. elif self.code in tuple('BHILQ'):
  183. self.signed = False
  184. self.min_value = 0
  185. self.max_value = 2L**self.bitsize - 1
  186. else:
  187. raise ValueError("unrecognized format code: %s" %
  188. self.code)
  189. def test_one(self, x, pack=struct.pack,
  190. unpack=struct.unpack,
  191. unhexlify=binascii.unhexlify):
  192. format = self.format
  193. if self.min_value <= x <= self.max_value:
  194. expected = long(x)
  195. if self.signed and x < 0:
  196. expected += 1L << self.bitsize
  197. self.assertGreaterEqual(expected, 0)
  198. expected = '%x' % expected
  199. if len(expected) & 1:
  200. expected = "0" + expected
  201. expected = unhexlify(expected)
  202. expected = ("\x00" * (self.bytesize - len(expected)) +
  203. expected)
  204. if (self.direction == '<' or
  205. self.direction in ('', '@', '=') and not ISBIGENDIAN):
  206. expected = string_reverse(expected)
  207. self.assertEqual(len(expected), self.bytesize)
  208. # Pack work?
  209. got = pack(format, x)
  210. self.assertEqual(got, expected)
  211. # Unpack work?
  212. retrieved = unpack(format, got)[0]
  213. self.assertEqual(x, retrieved)
  214. # Adding any byte should cause a "too big" error.
  215. self.assertRaises((struct.error, TypeError), unpack, format,
  216. '\x01' + got)
  217. else:
  218. # x is out of range -- verify pack realizes that.
  219. self.assertRaises((OverflowError, ValueError, struct.error),
  220. pack, format, x)
  221. def run(self):
  222. from random import randrange
  223. # Create all interesting powers of 2.
  224. values = []
  225. for exp in range(self.bitsize + 3):
  226. values.append(1L << exp)
  227. # Add some random values.
  228. for i in range(self.bitsize):
  229. val = 0L
  230. for j in range(self.bytesize):
  231. val = (val << 8) | randrange(256)
  232. values.append(val)
  233. # Values absorbed from other tests
  234. values.extend([300, 700000, sys.maxint*4])
  235. # Try all those, and their negations, and +-1 from
  236. # them. Note that this tests all power-of-2
  237. # boundaries in range, and a few out of range, plus
  238. # +-(2**n +- 1).
  239. for base in values:
  240. for val in -base, base:
  241. for incr in -1, 0, 1:
  242. x = val + incr
  243. self.test_one(int(x))
  244. self.test_one(long(x))
  245. # Some error cases.
  246. class NotAnIntNS(object):
  247. def __int__(self):
  248. return 42
  249. def __long__(self):
  250. return 1729L
  251. class NotAnIntOS:
  252. def __int__(self):
  253. return 85
  254. def __long__(self):
  255. return -163L
  256. # Objects with an '__index__' method should be allowed
  257. # to pack as integers. That is assuming the implemented
  258. # '__index__' method returns and 'int' or 'long'.
  259. class Indexable(object):
  260. def __init__(self, value):
  261. self._value = value
  262. def __index__(self):
  263. return self._value
  264. # If the '__index__' method raises a type error, then
  265. # '__int__' should be used with a deprecation warning.
  266. class BadIndex(object):
  267. def __index__(self):
  268. raise TypeError
  269. def __int__(self):
  270. return 42
  271. self.assertRaises((TypeError, struct.error),
  272. struct.pack, self.format,
  273. "a string")
  274. self.assertRaises((TypeError, struct.error),
  275. struct.pack, self.format,
  276. randrange)
  277. with check_warnings(("integer argument expected, "
  278. "got non-integer", DeprecationWarning)):
  279. with self.assertRaises((TypeError, struct.error)):
  280. struct.pack(self.format, 3+42j)
  281. # an attempt to convert a non-integer (with an
  282. # implicit conversion via __int__) should succeed,
  283. # with a DeprecationWarning
  284. for nonint in NotAnIntNS(), NotAnIntOS(), BadIndex():
  285. with check_warnings((".*integer argument expected, got non"
  286. "-integer", DeprecationWarning)) as w:
  287. got = struct.pack(self.format, nonint)
  288. lineno = inspect.currentframe().f_lineno - 1
  289. self.assertEqual(w.filename, testmod_filename)
  290. self.assertEqual(w.lineno, lineno)
  291. self.assertEqual(len(w.warnings), 1)
  292. expected = struct.pack(self.format, int(nonint))
  293. self.assertEqual(got, expected)
  294. # Check for legitimate values from '__index__'.
  295. for obj in (Indexable(0), Indexable(10), Indexable(17),
  296. Indexable(42), Indexable(100), Indexable(127)):
  297. try:
  298. struct.pack(format, obj)
  299. except:
  300. self.fail("integer code pack failed on object "
  301. "with '__index__' method")
  302. # Check for bogus values from '__index__'.
  303. for obj in (Indexable('a'), Indexable(u'b'), Indexable(None),
  304. Indexable({'a': 1}), Indexable([1, 2, 3])):
  305. self.assertRaises((TypeError, struct.error),
  306. struct.pack, self.format,
  307. obj)
  308. byteorders = '', '@', '=', '<', '>', '!'
  309. for code in integer_codes:
  310. for byteorder in byteorders:
  311. if (byteorder in ('', '@') and code in ('q', 'Q') and
  312. not HAVE_LONG_LONG):
  313. continue
  314. format = byteorder+code
  315. t = IntTester(format)
  316. t.run()
  317. def test_p_code(self):
  318. # Test p ("Pascal string") code.
  319. for code, input, expected, expectedback in [
  320. ('p','abc', '\x00', ''),
  321. ('1p', 'abc', '\x00', ''),
  322. ('2p', 'abc', '\x01a', 'a'),
  323. ('3p', 'abc', '\x02ab', 'ab'),
  324. ('4p', 'abc', '\x03abc', 'abc'),
  325. ('5p', 'abc', '\x03abc\x00', 'abc'),
  326. ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
  327. ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
  328. got = struct.pack(code, input)
  329. self.assertEqual(got, expected)
  330. (got,) = struct.unpack(code, got)
  331. self.assertEqual(got, expectedback)
  332. def test_705836(self):
  333. # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
  334. # from the low-order discarded bits could propagate into the exponent
  335. # field, causing the result to be wrong by a factor of 2.
  336. import math
  337. for base in range(1, 33):
  338. # smaller <- largest representable float less than base.
  339. delta = 0.5
  340. while base - delta / 2.0 != base:
  341. delta /= 2.0
  342. smaller = base - delta
  343. # Packing this rounds away a solid string of trailing 1 bits.
  344. packed = struct.pack("<f", smaller)
  345. unpacked = struct.unpack("<f", packed)[0]
  346. # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
  347. # 16, respectively.
  348. self.assertEqual(base, unpacked)
  349. bigpacked = struct.pack(">f", smaller)
  350. self.assertEqual(bigpacked, string_reverse(packed))
  351. unpacked = struct.unpack(">f", bigpacked)[0]
  352. self.assertEqual(base, unpacked)
  353. # Largest finite IEEE single.
  354. big = (1 << 24) - 1
  355. big = math.ldexp(big, 127 - 23)
  356. packed = struct.pack(">f", big)
  357. unpacked = struct.unpack(">f", packed)[0]
  358. self.assertEqual(big, unpacked)
  359. # The same, but tack on a 1 bit so it rounds up to infinity.
  360. big = (1 << 25) - 1
  361. big = math.ldexp(big, 127 - 24)
  362. self.assertRaises(OverflowError, struct.pack, ">f", big)
  363. def test_1530559(self):
  364. # SF bug 1530559. struct.pack raises TypeError where it used to convert.
  365. for endian in ('', '>', '<'):
  366. for fmt in integer_codes:
  367. self.check_float_coerce(endian + fmt, 1.0)
  368. self.check_float_coerce(endian + fmt, 1.5)
  369. def test_unpack_from(self, cls=str):
  370. data = cls('abcd01234')
  371. fmt = '4s'
  372. s = struct.Struct(fmt)
  373. self.assertEqual(s.unpack_from(data), ('abcd',))
  374. self.assertEqual(struct.unpack_from(fmt, data), ('abcd',))
  375. for i in xrange(6):
  376. self.assertEqual(s.unpack_from(data, i), (data[i:i+4],))
  377. self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
  378. for i in xrange(6, len(data) + 1):
  379. self.assertRaises(struct.error, s.unpack_from, data, i)
  380. self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
  381. def test_pack_into(self, cls=bytearray, tobytes=str):
  382. test_string = 'Reykjavik rocks, eow!'
  383. writable_buf = cls(' '*100)
  384. fmt = '21s'
  385. s = struct.Struct(fmt)
  386. # Test without offset
  387. s.pack_into(writable_buf, 0, test_string)
  388. from_buf = tobytes(writable_buf)[:len(test_string)]
  389. self.assertEqual(from_buf, test_string)
  390. # Test with offset.
  391. s.pack_into(writable_buf, 10, test_string)
  392. from_buf = tobytes(writable_buf)[:len(test_string)+10]
  393. self.assertEqual(from_buf, test_string[:10] + test_string)
  394. # Go beyond boundaries.
  395. small_buf = cls(' '*10)
  396. self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
  397. test_string)
  398. self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
  399. test_string)
  400. # Test bogus offset (issue 3694)
  401. sb = small_buf
  402. self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
  403. None)
  404. def test_pack_into_array(self):
  405. self.test_pack_into(cls=lambda b: array.array('c', b),
  406. tobytes=array.array.tostring)
  407. def test_pack_into_memoryview(self):
  408. # Issue #22113
  409. self.test_pack_into(cls=lambda b: memoryview(bytearray(b)),
  410. tobytes=memoryview.tobytes)
  411. def test_pack_into_fn(self):
  412. test_string = 'Reykjavik rocks, eow!'
  413. writable_buf = array.array('c', ' '*100)
  414. fmt = '21s'
  415. pack_into = lambda *args: struct.pack_into(fmt, *args)
  416. # Test without offset.
  417. pack_into(writable_buf, 0, test_string)
  418. from_buf = writable_buf.tostring()[:len(test_string)]
  419. self.assertEqual(from_buf, test_string)
  420. # Test with offset.
  421. pack_into(writable_buf, 10, test_string)
  422. from_buf = writable_buf.tostring()[:len(test_string)+10]
  423. self.assertEqual(from_buf, test_string[:10] + test_string)
  424. # Go beyond boundaries.
  425. small_buf = array.array('c', ' '*10)
  426. self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0,
  427. test_string)
  428. self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
  429. test_string)
  430. def test_unpack_with_buffer(self):
  431. with check_py3k_warnings(("buffer.. not supported in 3.x",
  432. DeprecationWarning)):
  433. # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
  434. data1 = array.array('B', '\x12\x34\x56\x78')
  435. data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
  436. for data in [data1, data2]:
  437. value, = struct.unpack('>I', data)
  438. self.assertEqual(value, 0x12345678)
  439. self.test_unpack_from(cls=buffer)
  440. def test_unpack_with_memoryview(self):
  441. # Bug 10212: struct.unpack doesn't support new buffer protocol objects
  442. data1 = memoryview('\x12\x34\x56\x78')
  443. for data in [data1,]:
  444. value, = struct.unpack('>I', data)
  445. self.assertEqual(value, 0x12345678)
  446. self.test_unpack_from(cls=memoryview)
  447. def test_bool(self):
  448. class ExplodingBool(object):
  449. def __nonzero__(self):
  450. raise IOError
  451. for prefix in tuple("<>!=")+('',):
  452. false = (), [], [], '', 0
  453. true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff//2
  454. falseFormat = prefix + '?' * len(false)
  455. packedFalse = struct.pack(falseFormat, *false)
  456. unpackedFalse = struct.unpack(falseFormat, packedFalse)
  457. trueFormat = prefix + '?' * len(true)
  458. packedTrue = struct.pack(trueFormat, *true)
  459. unpackedTrue = struct.unpack(trueFormat, packedTrue)
  460. self.assertEqual(len(true), len(unpackedTrue))
  461. self.assertEqual(len(false), len(unpackedFalse))
  462. for t in unpackedFalse:
  463. self.assertFalse(t)
  464. for t in unpackedTrue:
  465. self.assertTrue(t)
  466. packed = struct.pack(prefix+'?', 1)
  467. self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
  468. if len(packed) != 1:
  469. self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
  470. %packed)
  471. self.assertRaises(IOError, struct.pack, prefix + '?',
  472. ExplodingBool())
  473. for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
  474. self.assertTrue(struct.unpack('>?', c)[0])
  475. @unittest.skipUnless(IS32BIT, "Specific to 32bit machines")
  476. def test_crasher(self):
  477. self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
  478. def test_count_overflow(self):
  479. hugecount = '{}b'.format(sys.maxsize+1)
  480. self.assertRaises(struct.error, struct.calcsize, hugecount)
  481. hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
  482. self.assertRaises(struct.error, struct.calcsize, hugecount2)
  483. def check_sizeof(self, format_str, number_of_codes):
  484. # The size of 'PyStructObject'
  485. totalsize = support.calcobjsize('5P')
  486. # The size taken up by the 'formatcode' dynamic array
  487. totalsize += struct.calcsize('3P') * (number_of_codes + 1)
  488. support.check_sizeof(self, struct.Struct(format_str), totalsize)
  489. @support.cpython_only
  490. def test__sizeof__(self):
  491. for code in integer_codes:
  492. self.check_sizeof(code, 1)
  493. self.check_sizeof('BHILfdspP', 9)
  494. self.check_sizeof('B' * 1234, 1234)
  495. self.check_sizeof('fd', 2)
  496. self.check_sizeof('xxxxxxxxxxxxxx', 0)
  497. self.check_sizeof('100H', 100)
  498. self.check_sizeof('187s', 1)
  499. self.check_sizeof('20p', 1)
  500. self.check_sizeof('0s', 1)
  501. self.check_sizeof('0c', 0)
  502. def test_unicode_format(self):
  503. try:
  504. unicode
  505. except NameError:
  506. self.skipTest('no unicode support')
  507. # Issue #19099
  508. s = struct.Struct(unichr(ord('I')))
  509. self.assertEqual(s.format, 'I')
  510. self.assertIs(type(s.format), str)
  511. self.assertRaises(ValueError, struct.Struct, unichr(0x80))
  512. def test_main():
  513. support.run_unittest(StructTest)
  514. if __name__ == '__main__':
  515. test_main()