Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v8plus / lib / python2.4 / test / test_struct.py
CommitLineData
920dae64
AT
1from test.test_support import TestFailed, verbose, verify
2import struct
3
4import sys
5ISBIGENDIAN = sys.byteorder == "big"
6del sys
7verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
8 "bigendian determination appears wrong")
9
10def string_reverse(s):
11 chars = list(s)
12 chars.reverse()
13 return "".join(chars)
14
15def bigendian_to_native(value):
16 if ISBIGENDIAN:
17 return value
18 else:
19 return string_reverse(value)
20
21def simple_err(func, *args):
22 try:
23 func(*args)
24 except struct.error:
25 pass
26 else:
27 raise TestFailed, "%s%s did not raise struct.error" % (
28 func.__name__, args)
29
30def any_err(func, *args):
31 try:
32 func(*args)
33 except (struct.error, OverflowError, TypeError):
34 pass
35 else:
36 raise TestFailed, "%s%s did not raise error" % (
37 func.__name__, args)
38
39
40simple_err(struct.calcsize, 'Z')
41
42sz = struct.calcsize('i')
43if sz * 3 != struct.calcsize('iii'):
44 raise TestFailed, 'inconsistent sizes'
45
46fmt = 'cbxxxxxxhhhhiillffd'
47fmt3 = '3c3b18x12h6i6l6f3d'
48sz = struct.calcsize(fmt)
49sz3 = struct.calcsize(fmt3)
50if sz * 3 != sz3:
51 raise TestFailed, 'inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
52 fmt, sz, 3*sz, fmt3, sz3)
53
54simple_err(struct.pack, 'iii', 3)
55simple_err(struct.pack, 'i', 3, 3, 3)
56simple_err(struct.pack, 'i', 'foo')
57simple_err(struct.pack, 'P', 'foo')
58simple_err(struct.unpack, 'd', 'flap')
59s = struct.pack('ii', 1, 2)
60simple_err(struct.unpack, 'iii', s)
61simple_err(struct.unpack, 'i', s)
62
63c = 'a'
64b = 1
65h = 255
66i = 65535
67l = 65536
68f = 3.1415
69d = 3.1415
70
71for prefix in ('', '@', '<', '>', '=', '!'):
72 for format in ('xcbhilfd', 'xcBHILfd'):
73 format = prefix + format
74 if verbose:
75 print "trying:", format
76 s = struct.pack(format, c, b, h, i, l, f, d)
77 cp, bp, hp, ip, lp, fp, dp = struct.unpack(format, s)
78 if (cp != c or bp != b or hp != h or ip != i or lp != l or
79 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d)):
80 # ^^^ calculate only to two decimal places
81 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
82 str(format), str((cp, bp, hp, ip, lp, fp, dp)))
83
84# Test some of the new features in detail
85
86# (format, argument, big-endian result, little-endian result, asymmetric)
87tests = [
88 ('c', 'a', 'a', 'a', 0),
89 ('xc', 'a', '\0a', '\0a', 0),
90 ('cx', 'a', 'a\0', 'a\0', 0),
91 ('s', 'a', 'a', 'a', 0),
92 ('0s', 'helloworld', '', '', 1),
93 ('1s', 'helloworld', 'h', 'h', 1),
94 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
95 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
96 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
97 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
98 ('b', 7, '\7', '\7', 0),
99 ('b', -7, '\371', '\371', 0),
100 ('B', 7, '\7', '\7', 0),
101 ('B', 249, '\371', '\371', 0),
102 ('h', 700, '\002\274', '\274\002', 0),
103 ('h', -700, '\375D', 'D\375', 0),
104 ('H', 700, '\002\274', '\274\002', 0),
105 ('H', 0x10000-700, '\375D', 'D\375', 0),
106 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
107 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
108 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
109 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
110 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
111 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
112 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
113 ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
114 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
115 ('d', 2.0, '@\000\000\000\000\000\000\000',
116 '\000\000\000\000\000\000\000@', 0),
117 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
118 ('d', -2.0, '\300\000\000\000\000\000\000\000',
119 '\000\000\000\000\000\000\000\300', 0),
120]
121
122for fmt, arg, big, lil, asy in tests:
123 if verbose:
124 print "%r %r %r %r" % (fmt, arg, big, lil)
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 if res != exp:
129 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
130 fmt, arg, res, exp)
131 n = struct.calcsize(xfmt)
132 if n != len(res):
133 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
134 xfmt, n, len(res))
135 rev = struct.unpack(xfmt, res)[0]
136 if rev != arg and not asy:
137 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
138 fmt, res, rev, arg)
139
140###########################################################################
141# Simple native q/Q tests.
142
143has_native_qQ = 1
144try:
145 struct.pack("q", 5)
146except struct.error:
147 has_native_qQ = 0
148
149if verbose:
150 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
151
152any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
153simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
154simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
155
156def test_native_qQ():
157 bytes = struct.calcsize('q')
158 # The expected values here are in big-endian format, primarily because
159 # I'm on a little-endian machine and so this is the clearest way (for
160 # me) to force the code to get exercised.
161 for format, input, expected in (
162 ('q', -1, '\xff' * bytes),
163 ('q', 0, '\x00' * bytes),
164 ('Q', 0, '\x00' * bytes),
165 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
166 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
167 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
168 got = struct.pack(format, input)
169 native_expected = bigendian_to_native(expected)
170 verify(got == native_expected,
171 "%r-pack of %r gave %r, not %r" %
172 (format, input, got, native_expected))
173 retrieved = struct.unpack(format, got)[0]
174 verify(retrieved == input,
175 "%r-unpack of %r gave %r, not %r" %
176 (format, got, retrieved, input))
177
178if has_native_qQ:
179 test_native_qQ()
180
181###########################################################################
182# Standard integer tests (bBhHiIlLqQ).
183
184import binascii
185
186class IntTester:
187
188 # XXX Most std integer modes fail to test for out-of-range.
189 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
190 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
191 # reported by Mark Favas).
192 BUGGY_RANGE_CHECK = "bBhHiIlL"
193
194 def __init__(self, formatpair, bytesize):
195 assert len(formatpair) == 2
196 self.formatpair = formatpair
197 for direction in "<>!=":
198 for code in formatpair:
199 format = direction + code
200 verify(struct.calcsize(format) == bytesize)
201 self.bytesize = bytesize
202 self.bitsize = bytesize * 8
203 self.signed_code, self.unsigned_code = formatpair
204 self.unsigned_min = 0
205 self.unsigned_max = 2L**self.bitsize - 1
206 self.signed_min = -(2L**(self.bitsize-1))
207 self.signed_max = 2L**(self.bitsize-1) - 1
208
209 def test_one(self, x, pack=struct.pack,
210 unpack=struct.unpack,
211 unhexlify=binascii.unhexlify):
212 if verbose:
213 print "trying std", self.formatpair, "on", x, "==", hex(x)
214
215 # Try signed.
216 code = self.signed_code
217 if self.signed_min <= x <= self.signed_max:
218 # Try big-endian.
219 expected = long(x)
220 if x < 0:
221 expected += 1L << self.bitsize
222 assert expected > 0
223 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
224 if len(expected) & 1:
225 expected = "0" + expected
226 expected = unhexlify(expected)
227 expected = "\x00" * (self.bytesize - len(expected)) + expected
228
229 # Pack work?
230 format = ">" + code
231 got = pack(format, x)
232 verify(got == expected,
233 "'%s'-pack of %r gave %r, not %r" %
234 (format, x, got, expected))
235
236 # Unpack work?
237 retrieved = unpack(format, got)[0]
238 verify(x == retrieved,
239 "'%s'-unpack of %r gave %r, not %r" %
240 (format, got, retrieved, x))
241
242 # Adding any byte should cause a "too big" error.
243 any_err(unpack, format, '\x01' + got)
244
245 # Try little-endian.
246 format = "<" + code
247 expected = string_reverse(expected)
248
249 # Pack work?
250 got = pack(format, x)
251 verify(got == expected,
252 "'%s'-pack of %r gave %r, not %r" %
253 (format, x, got, expected))
254
255 # Unpack work?
256 retrieved = unpack(format, got)[0]
257 verify(x == retrieved,
258 "'%s'-unpack of %r gave %r, not %r" %
259 (format, got, retrieved, x))
260
261 # Adding any byte should cause a "too big" error.
262 any_err(unpack, format, '\x01' + got)
263
264 else:
265 # x is out of range -- verify pack realizes that.
266 if code in self.BUGGY_RANGE_CHECK:
267 if verbose:
268 print "Skipping buggy range check for code", code
269 else:
270 any_err(pack, ">" + code, x)
271 any_err(pack, "<" + code, x)
272
273 # Much the same for unsigned.
274 code = self.unsigned_code
275 if self.unsigned_min <= x <= self.unsigned_max:
276 # Try big-endian.
277 format = ">" + code
278 expected = long(x)
279 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
280 if len(expected) & 1:
281 expected = "0" + expected
282 expected = unhexlify(expected)
283 expected = "\x00" * (self.bytesize - len(expected)) + expected
284
285 # Pack work?
286 got = pack(format, x)
287 verify(got == expected,
288 "'%s'-pack of %r gave %r, not %r" %
289 (format, x, got, expected))
290
291 # Unpack work?
292 retrieved = unpack(format, got)[0]
293 verify(x == retrieved,
294 "'%s'-unpack of %r gave %r, not %r" %
295 (format, got, retrieved, x))
296
297 # Adding any byte should cause a "too big" error.
298 any_err(unpack, format, '\x01' + got)
299
300 # Try little-endian.
301 format = "<" + code
302 expected = string_reverse(expected)
303
304 # Pack work?
305 got = pack(format, x)
306 verify(got == expected,
307 "'%s'-pack of %r gave %r, not %r" %
308 (format, x, got, expected))
309
310 # Unpack work?
311 retrieved = unpack(format, got)[0]
312 verify(x == retrieved,
313 "'%s'-unpack of %r gave %r, not %r" %
314 (format, got, retrieved, x))
315
316 # Adding any byte should cause a "too big" error.
317 any_err(unpack, format, '\x01' + got)
318
319 else:
320 # x is out of range -- verify pack realizes that.
321 if code in self.BUGGY_RANGE_CHECK:
322 if verbose:
323 print "Skipping buggy range check for code", code
324 else:
325 any_err(pack, ">" + code, x)
326 any_err(pack, "<" + code, x)
327
328 def run(self):
329 from random import randrange
330
331 # Create all interesting powers of 2.
332 values = []
333 for exp in range(self.bitsize + 3):
334 values.append(1L << exp)
335
336 # Add some random values.
337 for i in range(self.bitsize):
338 val = 0L
339 for j in range(self.bytesize):
340 val = (val << 8) | randrange(256)
341 values.append(val)
342
343 # Try all those, and their negations, and +-1 from them. Note
344 # that this tests all power-of-2 boundaries in range, and a few out
345 # of range, plus +-(2**n +- 1).
346 for base in values:
347 for val in -base, base:
348 for incr in -1, 0, 1:
349 x = val + incr
350 try:
351 x = int(x)
352 except OverflowError:
353 pass
354 self.test_one(x)
355
356 # Some error cases.
357 for direction in "<>":
358 for code in self.formatpair:
359 for badobject in "a string", 3+42j, randrange:
360 any_err(struct.pack, direction + code, badobject)
361
362for args in [("bB", 1),
363 ("hH", 2),
364 ("iI", 4),
365 ("lL", 4),
366 ("qQ", 8)]:
367 t = IntTester(*args)
368 t.run()
369
370
371###########################################################################
372# The p ("Pascal string") code.
373
374def test_p_code():
375 for code, input, expected, expectedback in [
376 ('p','abc', '\x00', ''),
377 ('1p', 'abc', '\x00', ''),
378 ('2p', 'abc', '\x01a', 'a'),
379 ('3p', 'abc', '\x02ab', 'ab'),
380 ('4p', 'abc', '\x03abc', 'abc'),
381 ('5p', 'abc', '\x03abc\x00', 'abc'),
382 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
383 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
384 got = struct.pack(code, input)
385 if got != expected:
386 raise TestFailed("pack(%r, %r) == %r but expected %r" %
387 (code, input, got, expected))
388 (got,) = struct.unpack(code, got)
389 if got != expectedback:
390 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
391 (code, input, got, expectedback))
392
393test_p_code()
394
395
396###########################################################################
397# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
398# from the low-order discarded bits could propagate into the exponent
399# field, causing the result to be wrong by a factor of 2.
400
401def test_705836():
402 import math
403
404 for base in range(1, 33):
405 # smaller <- largest representable float less than base.
406 delta = 0.5
407 while base - delta / 2.0 != base:
408 delta /= 2.0
409 smaller = base - delta
410 # Packing this rounds away a solid string of trailing 1 bits.
411 packed = struct.pack("<f", smaller)
412 unpacked = struct.unpack("<f", packed)[0]
413 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
414 # 16, respectively.
415 verify(base == unpacked)
416 bigpacked = struct.pack(">f", smaller)
417 verify(bigpacked == string_reverse(packed),
418 ">f pack should be byte-reversal of <f pack")
419 unpacked = struct.unpack(">f", bigpacked)[0]
420 verify(base == unpacked)
421
422 # Largest finite IEEE single.
423 big = (1 << 24) - 1
424 big = math.ldexp(big, 127 - 23)
425 packed = struct.pack(">f", big)
426 unpacked = struct.unpack(">f", packed)[0]
427 verify(big == unpacked)
428
429 # The same, but tack on a 1 bit so it rounds up to infinity.
430 big = (1 << 25) - 1
431 big = math.ldexp(big, 127 - 24)
432 try:
433 packed = struct.pack(">f", big)
434 except OverflowError:
435 pass
436 else:
437 TestFailed("expected OverflowError")
438
439test_705836()