]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_struct.py
6 from test
.test_support
import run_unittest
, check_warnings
, check_py3k_warnings
9 ISBIGENDIAN
= sys
.byteorder
== "big"
10 IS32BIT
= sys
.maxsize
== 0x7fffffff
12 integer_codes
= 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'
14 testmod_filename
= os
.path
.splitext(__file__
)[0] + '.py'
15 # Native 'q' packing isn't available on systems that don't have the C
20 HAVE_LONG_LONG
= False
24 def string_reverse(s
):
25 return "".join(reversed(s
))
27 def bigendian_to_native(value
):
31 return string_reverse(value
)
33 class StructTest(unittest
.TestCase
):
35 def check_float_coerce(self
, format
, number
):
36 # SF bug 1530559. struct.pack raises TypeError where it used
38 with
check_warnings((".*integer argument expected, got float",
39 DeprecationWarning)) as w
:
40 got
= struct
.pack(format
, number
)
41 lineno
= inspect
.currentframe().f_lineno
- 1
42 self
.assertEqual(w
.filename
, testmod_filename
)
43 self
.assertEqual(w
.lineno
, lineno
)
44 self
.assertEqual(len(w
.warnings
), 1)
45 expected
= struct
.pack(format
, int(number
))
46 self
.assertEqual(got
, expected
)
48 def test_isbigendian(self
):
49 self
.assertEqual((struct
.pack('=i', 1)[0] == chr(0)), ISBIGENDIAN
)
51 def test_consistence(self
):
52 self
.assertRaises(struct
.error
, struct
.calcsize
, 'Z')
54 sz
= struct
.calcsize('i')
55 self
.assertEqual(sz
* 3, struct
.calcsize('iii'))
57 fmt
= 'cbxxxxxxhhhhiillffd?'
58 fmt3
= '3c3b18x12h6i6l6f3d3?'
59 sz
= struct
.calcsize(fmt
)
60 sz3
= struct
.calcsize(fmt3
)
61 self
.assertEqual(sz
* 3, sz3
)
63 self
.assertRaises(struct
.error
, struct
.pack
, 'iii', 3)
64 self
.assertRaises(struct
.error
, struct
.pack
, 'i', 3, 3, 3)
65 self
.assertRaises((TypeError, struct
.error
), struct
.pack
, 'i', 'foo')
66 self
.assertRaises((TypeError, struct
.error
), struct
.pack
, 'P', 'foo')
67 self
.assertRaises(struct
.error
, struct
.unpack
, 'd', 'flap')
68 s
= struct
.pack('ii', 1, 2)
69 self
.assertRaises(struct
.error
, struct
.unpack
, 'iii', s
)
70 self
.assertRaises(struct
.error
, struct
.unpack
, 'i', s
)
72 def test_transitiveness(self
):
82 for prefix
in ('', '@', '<', '>', '=', '!'):
83 for format
in ('xcbhilfd?', 'xcBHILfd?'):
84 format
= prefix
+ format
85 s
= struct
.pack(format
, c
, b
, h
, i
, l
, f
, d
, t
)
86 cp
, bp
, hp
, ip
, lp
, fp
, dp
, tp
= struct
.unpack(format
, s
)
87 self
.assertEqual(cp
, c
)
88 self
.assertEqual(bp
, b
)
89 self
.assertEqual(hp
, h
)
90 self
.assertEqual(ip
, i
)
91 self
.assertEqual(lp
, l
)
92 self
.assertEqual(int(100 * fp
), int(100 * f
))
93 self
.assertEqual(int(100 * dp
), int(100 * d
))
94 self
.assertEqual(tp
, t
)
96 def test_new_features(self
):
97 # Test some of the new features in detail
98 # (format, argument, big-endian result, little-endian result, asymmetric)
100 ('c', 'a', 'a', 'a', 0),
101 ('xc', 'a', '\0a', '\0a', 0),
102 ('cx', 'a', 'a\0', 'a\0', 0),
103 ('s', 'a', 'a', 'a', 0),
104 ('0s', 'helloworld', '', '', 1),
105 ('1s', 'helloworld', 'h', 'h', 1),
106 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
107 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
108 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
109 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
110 ('b', 7, '\7', '\7', 0),
111 ('b', -7, '\371', '\371', 0),
112 ('B', 7, '\7', '\7', 0),
113 ('B', 249, '\371', '\371', 0),
114 ('h', 700, '\002\274', '\274\002', 0),
115 ('h', -700, '\375D', 'D\375', 0),
116 ('H', 700, '\002\274', '\274\002', 0),
117 ('H', 0x10000-700, '\375D', 'D\375', 0),
118 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
119 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
120 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
121 ('I', 0x100000000L
-70000000, '\373\323\342\200', '\200\342\323\373', 0),
122 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
123 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
124 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
125 ('L', 0x100000000L
-70000000, '\373\323\342\200', '\200\342\323\373', 0),
126 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
127 ('d', 2.0, '@\000\000\000\000\000\000\000',
128 '\000\000\000\000\000\000\000@', 0),
129 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
130 ('d', -2.0, '\300\000\000\000\000\000\000\000',
131 '\000\000\000\000\000\000\000\300', 0),
132 ('?', 0, '\0', '\0', 0),
133 ('?', 3, '\1', '\1', 1),
134 ('?', True, '\1', '\1', 0),
135 ('?', [], '\0', '\0', 1),
136 ('?', (1,), '\1', '\1', 1),
139 for fmt
, arg
, big
, lil
, asy
in tests
:
140 for (xfmt
, exp
) in [('>'+fmt
, big
), ('!'+fmt
, big
), ('<'+fmt
, lil
),
141 ('='+fmt
, ISBIGENDIAN
and big
or lil
)]:
142 res
= struct
.pack(xfmt
, arg
)
143 self
.assertEqual(res
, exp
)
144 self
.assertEqual(struct
.calcsize(xfmt
), len(res
))
145 rev
= struct
.unpack(xfmt
, res
)[0]
149 def test_calcsize(self
):
158 # standard integer sizes
159 for code
in integer_codes
:
160 for byteorder
in ('=', '<', '>', '!'):
161 format
= byteorder
+code
162 size
= struct
.calcsize(format
)
163 self
.assertEqual(size
, expected_size
[code
])
165 # native integer sizes, except 'q' and 'Q'
166 for format_pair
in ('bB', 'hH', 'iI', 'lL'):
167 for byteorder
in ['', '@']:
168 signed_size
= struct
.calcsize(byteorder
+ format_pair
[0])
169 unsigned_size
= struct
.calcsize(byteorder
+ format_pair
[1])
170 self
.assertEqual(signed_size
, unsigned_size
)
172 # bounds for native integer sizes
173 self
.assertEqual(struct
.calcsize('b'), 1)
174 self
.assertLessEqual(2, struct
.calcsize('h'))
175 self
.assertLessEqual(4, struct
.calcsize('l'))
176 self
.assertLessEqual(struct
.calcsize('h'), struct
.calcsize('i'))
177 self
.assertLessEqual(struct
.calcsize('i'), struct
.calcsize('l'))
179 # tests for native 'q' and 'Q' when applicable
181 self
.assertEqual(struct
.calcsize('q'), struct
.calcsize('Q'))
182 self
.assertLessEqual(8, struct
.calcsize('q'))
183 self
.assertLessEqual(struct
.calcsize('l'), struct
.calcsize('q'))
185 def test_integers(self
):
186 # Integer tests (bBhHiIlLqQ).
189 class IntTester(unittest
.TestCase
):
190 def __init__(self
, format
):
191 super(IntTester
, self
).__init
__(methodName
='test_one')
193 self
.code
= format
[-1]
194 self
.direction
= format
[:-1]
195 if not self
.direction
in ('', '@', '=', '<', '>', '!'):
196 raise ValueError("unrecognized packing direction: %s" %
198 self
.bytesize
= struct
.calcsize(format
)
199 self
.bitsize
= self
.bytesize
* 8
200 if self
.code
in tuple('bhilq'):
202 self
.min_value
= -(2L**(self
.bitsize
-1))
203 self
.max_value
= 2L**(self
.bitsize
-1) - 1
204 elif self
.code
in tuple('BHILQ'):
207 self
.max_value
= 2L**self
.bitsize
- 1
209 raise ValueError("unrecognized format code: %s" %
212 def test_one(self
, x
, pack
=struct
.pack
,
213 unpack
=struct
.unpack
,
214 unhexlify
=binascii
.unhexlify
):
217 if self
.min_value
<= x
<= self
.max_value
:
219 if self
.signed
and x
< 0:
220 expected
+= 1L << self
.bitsize
221 self
.assertGreaterEqual(expected
, 0)
222 expected
= '%x' % expected
223 if len(expected
) & 1:
224 expected
= "0" + expected
225 expected
= unhexlify(expected
)
226 expected
= ("\x00" * (self
.bytesize
- len(expected
)) +
228 if (self
.direction
== '<' or
229 self
.direction
in ('', '@', '=') and not ISBIGENDIAN
):
230 expected
= string_reverse(expected
)
231 self
.assertEqual(len(expected
), self
.bytesize
)
234 got
= pack(format
, x
)
235 self
.assertEqual(got
, expected
)
238 retrieved
= unpack(format
, got
)[0]
239 self
.assertEqual(x
, retrieved
)
241 # Adding any byte should cause a "too big" error.
242 self
.assertRaises((struct
.error
, TypeError), unpack
, format
,
245 # x is out of range -- verify pack realizes that.
246 self
.assertRaises((OverflowError, ValueError, struct
.error
),
250 from random
import randrange
252 # Create all interesting powers of 2.
254 for exp
in range(self
.bitsize
+ 3):
255 values
.append(1L << exp
)
257 # Add some random values.
258 for i
in range(self
.bitsize
):
260 for j
in range(self
.bytesize
):
261 val
= (val
<< 8) |
randrange(256)
264 # Values absorbed from other tests
265 values
.extend([300, 700000, sys
.maxint
*4])
267 # Try all those, and their negations, and +-1 from
268 # them. Note that this tests all power-of-2
269 # boundaries in range, and a few out of range, plus
272 for val
in -base
, base
:
273 for incr
in -1, 0, 1:
275 self
.test_one(int(x
))
276 self
.test_one(long(x
))
279 class NotAnIntNS(object):
293 # Objects with an '__index__' method should be allowed
294 # to pack as integers. That is assuming the implemented
295 # '__index__' method returns and 'int' or 'long'.
296 class Indexable(object):
297 def __init__(self
, value
):
303 # If the '__index__' method raises a type error, then
304 # '__int__' should be used with a deprecation warning.
305 class BadIndex(object):
312 self
.assertRaises((TypeError, struct
.error
),
313 struct
.pack
, self
.format
,
315 self
.assertRaises((TypeError, struct
.error
),
316 struct
.pack
, self
.format
,
318 with
check_warnings(("integer argument expected, "
319 "got non-integer", DeprecationWarning)):
320 with self
.assertRaises((TypeError, struct
.error
)):
321 struct
.pack(self
.format
, 3+42j
)
323 # an attempt to convert a non-integer (with an
324 # implicit conversion via __int__) should succeed,
325 # with a DeprecationWarning
326 for nonint
in NotAnIntNS(), NotAnIntOS(), BadIndex():
327 with
check_warnings((".*integer argument expected, got non"
328 "-integer", DeprecationWarning)) as w
:
329 got
= struct
.pack(self
.format
, nonint
)
330 lineno
= inspect
.currentframe().f_lineno
- 1
331 self
.assertEqual(w
.filename
, testmod_filename
)
332 self
.assertEqual(w
.lineno
, lineno
)
333 self
.assertEqual(len(w
.warnings
), 1)
334 expected
= struct
.pack(self
.format
, int(nonint
))
335 self
.assertEqual(got
, expected
)
337 # Check for legitimate values from '__index__'.
338 for obj
in (Indexable(0), Indexable(10), Indexable(17),
339 Indexable(42), Indexable(100), Indexable(127)):
341 struct
.pack(format
, obj
)
343 self
.fail("integer code pack failed on object "
344 "with '__index__' method")
346 # Check for bogus values from '__index__'.
347 for obj
in (Indexable('a'), Indexable(u
'b'), Indexable(None),
348 Indexable({'a': 1}), Indexable([1, 2, 3])):
349 self
.assertRaises((TypeError, struct
.error
),
350 struct
.pack
, self
.format
,
353 byteorders
= '', '@', '=', '<', '>', '!'
354 for code
in integer_codes
:
355 for byteorder
in byteorders
:
356 if (byteorder
in ('', '@') and code
in ('q', 'Q') and
359 format
= byteorder
+code
360 t
= IntTester(format
)
363 def test_p_code(self
):
364 # Test p ("Pascal string") code.
365 for code
, input, expected
, expectedback
in [
366 ('p','abc', '\x00', ''),
367 ('1p', 'abc', '\x00', ''),
368 ('2p', 'abc', '\x01a', 'a'),
369 ('3p', 'abc', '\x02ab', 'ab'),
370 ('4p', 'abc', '\x03abc', 'abc'),
371 ('5p', 'abc', '\x03abc\x00', 'abc'),
372 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
373 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
374 got
= struct
.pack(code
, input)
375 self
.assertEqual(got
, expected
)
376 (got
,) = struct
.unpack(code
, got
)
377 self
.assertEqual(got
, expectedback
)
379 def test_705836(self
):
380 # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
381 # from the low-order discarded bits could propagate into the exponent
382 # field, causing the result to be wrong by a factor of 2.
385 for base
in range(1, 33):
386 # smaller <- largest representable float less than base.
388 while base
- delta
/ 2.0 != base
:
390 smaller
= base
- delta
391 # Packing this rounds away a solid string of trailing 1 bits.
392 packed
= struct
.pack("<f", smaller
)
393 unpacked
= struct
.unpack("<f", packed
)[0]
394 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
396 self
.assertEqual(base
, unpacked
)
397 bigpacked
= struct
.pack(">f", smaller
)
398 self
.assertEqual(bigpacked
, string_reverse(packed
))
399 unpacked
= struct
.unpack(">f", bigpacked
)[0]
400 self
.assertEqual(base
, unpacked
)
402 # Largest finite IEEE single.
404 big
= math
.ldexp(big
, 127 - 23)
405 packed
= struct
.pack(">f", big
)
406 unpacked
= struct
.unpack(">f", packed
)[0]
407 self
.assertEqual(big
, unpacked
)
409 # The same, but tack on a 1 bit so it rounds up to infinity.
411 big
= math
.ldexp(big
, 127 - 24)
412 self
.assertRaises(OverflowError, struct
.pack
, ">f", big
)
414 def test_1530559(self
):
415 # SF bug 1530559. struct.pack raises TypeError where it used to convert.
416 for endian
in ('', '>', '<'):
417 for fmt
in integer_codes
:
418 self
.check_float_coerce(endian
+ fmt
, 1.0)
419 self
.check_float_coerce(endian
+ fmt
, 1.5)
421 def test_unpack_from(self
, cls
=str):
422 data
= cls('abcd01234')
424 s
= struct
.Struct(fmt
)
426 self
.assertEqual(s
.unpack_from(data
), ('abcd',))
427 self
.assertEqual(struct
.unpack_from(fmt
, data
), ('abcd',))
429 self
.assertEqual(s
.unpack_from(data
, i
), (data
[i
:i
+4],))
430 self
.assertEqual(struct
.unpack_from(fmt
, data
, i
), (data
[i
:i
+4],))
431 for i
in xrange(6, len(data
) + 1):
432 self
.assertRaises(struct
.error
, s
.unpack_from
, data
, i
)
433 self
.assertRaises(struct
.error
, struct
.unpack_from
, fmt
, data
, i
)
435 def test_pack_into(self
):
436 test_string
= 'Reykjavik rocks, eow!'
437 writable_buf
= array
.array('c', ' '*100)
439 s
= struct
.Struct(fmt
)
441 # Test without offset
442 s
.pack_into(writable_buf
, 0, test_string
)
443 from_buf
= writable_buf
.tostring()[:len(test_string
)]
444 self
.assertEqual(from_buf
, test_string
)
447 s
.pack_into(writable_buf
, 10, test_string
)
448 from_buf
= writable_buf
.tostring()[:len(test_string
)+10]
449 self
.assertEqual(from_buf
, test_string
[:10] + test_string
)
451 # Go beyond boundaries.
452 small_buf
= array
.array('c', ' '*10)
453 self
.assertRaises((ValueError, struct
.error
), s
.pack_into
, small_buf
, 0,
455 self
.assertRaises((ValueError, struct
.error
), s
.pack_into
, small_buf
, 2,
458 # Test bogus offset (issue 3694)
460 self
.assertRaises((TypeError, struct
.error
), struct
.pack_into
, b
'', sb
,
463 def test_pack_into_fn(self
):
464 test_string
= 'Reykjavik rocks, eow!'
465 writable_buf
= array
.array('c', ' '*100)
467 pack_into
= lambda *args
: struct
.pack_into(fmt
, *args
)
469 # Test without offset.
470 pack_into(writable_buf
, 0, test_string
)
471 from_buf
= writable_buf
.tostring()[:len(test_string
)]
472 self
.assertEqual(from_buf
, test_string
)
475 pack_into(writable_buf
, 10, test_string
)
476 from_buf
= writable_buf
.tostring()[:len(test_string
)+10]
477 self
.assertEqual(from_buf
, test_string
[:10] + test_string
)
479 # Go beyond boundaries.
480 small_buf
= array
.array('c', ' '*10)
481 self
.assertRaises((ValueError, struct
.error
), pack_into
, small_buf
, 0,
483 self
.assertRaises((ValueError, struct
.error
), pack_into
, small_buf
, 2,
486 def test_unpack_with_buffer(self
):
487 with
check_py3k_warnings(("buffer.. not supported in 3.x",
488 DeprecationWarning)):
489 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects
490 data1
= array
.array('B', '\x12\x34\x56\x78')
491 data2
= buffer('......\x12\x34\x56\x78......', 6, 4)
492 for data
in [data1
, data2
]:
493 value
, = struct
.unpack('>I', data
)
494 self
.assertEqual(value
, 0x12345678)
496 self
.test_unpack_from(cls
=buffer)
499 class ExplodingBool(object):
500 def __nonzero__(self
):
502 for prefix
in tuple("<>!=")+('',):
503 false
= (), [], [], '', 0
504 true
= [1], 'test', 5, -1, 0xffffffffL
+1, 0xffffffff//2
506 falseFormat
= prefix
+ '?' * len(false
)
507 packedFalse
= struct
.pack(falseFormat
, *false
)
508 unpackedFalse
= struct
.unpack(falseFormat
, packedFalse
)
510 trueFormat
= prefix
+ '?' * len(true
)
511 packedTrue
= struct
.pack(trueFormat
, *true
)
512 unpackedTrue
= struct
.unpack(trueFormat
, packedTrue
)
514 self
.assertEqual(len(true
), len(unpackedTrue
))
515 self
.assertEqual(len(false
), len(unpackedFalse
))
517 for t
in unpackedFalse
:
519 for t
in unpackedTrue
:
522 packed
= struct
.pack(prefix
+'?', 1)
524 self
.assertEqual(len(packed
), struct
.calcsize(prefix
+'?'))
527 self
.assertFalse(prefix
, msg
='encoded bool is not one byte: %r'
530 self
.assertRaises(IOError, struct
.pack
, prefix
+ '?',
533 for c
in [b
'\x01', b
'\x7f', b
'\xff', b
'\x0f', b
'\xf0']:
534 self
.assertTrue(struct
.unpack('>?', c
)[0])
536 @unittest.skipUnless(IS32BIT
, "Specific to 32bit machines")
537 def test_crasher(self
):
538 self
.assertRaises(MemoryError, struct
.pack
, "357913941c", "a")
540 def test_count_overflow(self
):
541 hugecount
= '{}b'.format(sys
.maxsize
+1)
542 self
.assertRaises(struct
.error
, struct
.calcsize
, hugecount
)
544 hugecount2
= '{}b{}H'.format(sys
.maxsize
//2, sys
.maxsize
//2)
545 self
.assertRaises(struct
.error
, struct
.calcsize
, hugecount2
)
548 run_unittest(StructTest
)
550 if __name__
== '__main__':