blob: 1420a08ce2d363bc20c9ea23daaea8d1321cdc7d [file] [log] [blame]
Barry Warsaw04f357c2002-07-23 19:04:11 +00001from test.test_support import TestFailed, verbose, verify
Martin Blais2856e5f2006-05-26 12:03:27 +00002import test.test_support
Barry Warsaw07a0eec1996-12-12 23:34:06 +00003import struct
Martin Blais2856e5f2006-05-26 12:03:27 +00004import array
5import unittest
Barry Warsaw07a0eec1996-12-12 23:34:06 +00006
Tim Peters17e17d42001-06-13 22:45:27 +00007import sys
8ISBIGENDIAN = sys.byteorder == "big"
9del sys
10verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN,
11 "bigendian determination appears wrong")
12
13def string_reverse(s):
14 chars = list(s)
15 chars.reverse()
16 return "".join(chars)
17
18def bigendian_to_native(value):
19 if ISBIGENDIAN:
20 return value
21 else:
22 return string_reverse(value)
23
Barry Warsaw07a0eec1996-12-12 23:34:06 +000024def simple_err(func, *args):
25 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000026 func(*args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000027 except struct.error:
Guido van Rossum41360a41998-03-26 19:42:58 +000028 pass
Barry Warsaw07a0eec1996-12-12 23:34:06 +000029 else:
Guido van Rossum41360a41998-03-26 19:42:58 +000030 raise TestFailed, "%s%s did not raise struct.error" % (
31 func.__name__, args)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000032
Tim Peters7a3bfc32001-06-12 01:22:22 +000033def any_err(func, *args):
34 try:
Guido van Rossum68468eb2003-02-27 20:14:51 +000035 func(*args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000036 except (struct.error, OverflowError, TypeError):
37 pass
38 else:
39 raise TestFailed, "%s%s did not raise error" % (
40 func.__name__, args)
Tim Peters7a3bfc32001-06-12 01:22:22 +000041
Tim Peters17e17d42001-06-13 22:45:27 +000042
Tim Peters7b9542a2001-06-10 23:40:19 +000043simple_err(struct.calcsize, 'Z')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000044
45sz = struct.calcsize('i')
Fred Drake132dce22000-12-12 23:11:42 +000046if sz * 3 != struct.calcsize('iii'):
Guido van Rossum2a378501996-12-31 17:25:47 +000047 raise TestFailed, 'inconsistent sizes'
Barry Warsaw07a0eec1996-12-12 23:34:06 +000048
Guido van Rossum04ebf5c1997-01-03 19:00:37 +000049fmt = 'cbxxxxxxhhhhiillffd'
50fmt3 = '3c3b18x12h6i6l6f3d'
51sz = struct.calcsize(fmt)
52sz3 = struct.calcsize(fmt3)
Fred Drake132dce22000-12-12 23:11:42 +000053if sz * 3 != sz3:
Walter Dörwald70a6b492004-02-12 17:35:32 +000054 raise TestFailed, 'inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
55 fmt, sz, 3*sz, fmt3, sz3)
Barry Warsaw07a0eec1996-12-12 23:34:06 +000056
57simple_err(struct.pack, 'iii', 3)
58simple_err(struct.pack, 'i', 3, 3, 3)
59simple_err(struct.pack, 'i', 'foo')
Armin Rigo9f904392004-09-27 19:27:51 +000060simple_err(struct.pack, 'P', 'foo')
Barry Warsaw07a0eec1996-12-12 23:34:06 +000061simple_err(struct.unpack, 'd', 'flap')
62s = struct.pack('ii', 1, 2)
63simple_err(struct.unpack, 'iii', s)
64simple_err(struct.unpack, 'i', s)
65
66c = 'a'
Guido van Rossum2a378501996-12-31 17:25:47 +000067b = 1
Barry Warsaw07a0eec1996-12-12 23:34:06 +000068h = 255
69i = 65535
70l = 65536
71f = 3.1415
72d = 3.1415
73
Guido van Rossum420c11c1997-01-03 00:09:46 +000074for prefix in ('', '@', '<', '>', '=', '!'):
75 for format in ('xcbhilfd', 'xcBHILfd'):
Guido van Rossum41360a41998-03-26 19:42:58 +000076 format = prefix + format
77 if verbose:
78 print "trying:", format
79 s = struct.pack(format, c, b, h, i, l, f, d)
80 cp, bp, hp, ip, lp, fp, dp = struct.unpack(format, s)
Fred Drake132dce22000-12-12 23:11:42 +000081 if (cp != c or bp != b or hp != h or ip != i or lp != l or
82 int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d)):
Guido van Rossum41360a41998-03-26 19:42:58 +000083 # ^^^ calculate only to two decimal places
84 raise TestFailed, "unpack/pack not transitive (%s, %s)" % (
85 str(format), str((cp, bp, hp, ip, lp, fp, dp)))
Guido van Rossum2a378501996-12-31 17:25:47 +000086
Guido van Rossum420c11c1997-01-03 00:09:46 +000087# Test some of the new features in detail
Guido van Rossum2a378501996-12-31 17:25:47 +000088
89# (format, argument, big-endian result, little-endian result, asymmetric)
90tests = [
91 ('c', 'a', 'a', 'a', 0),
92 ('xc', 'a', '\0a', '\0a', 0),
93 ('cx', 'a', 'a\0', 'a\0', 0),
94 ('s', 'a', 'a', 'a', 0),
95 ('0s', 'helloworld', '', '', 1),
96 ('1s', 'helloworld', 'h', 'h', 1),
97 ('9s', 'helloworld', 'helloworl', 'helloworl', 1),
98 ('10s', 'helloworld', 'helloworld', 'helloworld', 0),
99 ('11s', 'helloworld', 'helloworld\0', 'helloworld\0', 1),
100 ('20s', 'helloworld', 'helloworld'+10*'\0', 'helloworld'+10*'\0', 1),
101 ('b', 7, '\7', '\7', 0),
102 ('b', -7, '\371', '\371', 0),
103 ('B', 7, '\7', '\7', 0),
104 ('B', 249, '\371', '\371', 0),
105 ('h', 700, '\002\274', '\274\002', 0),
106 ('h', -700, '\375D', 'D\375', 0),
107 ('H', 700, '\002\274', '\274\002', 0),
108 ('H', 0x10000-700, '\375D', 'D\375', 0),
109 ('i', 70000000, '\004,\035\200', '\200\035,\004', 0),
110 ('i', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
111 ('I', 70000000L, '\004,\035\200', '\200\035,\004', 0),
112 ('I', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
113 ('l', 70000000, '\004,\035\200', '\200\035,\004', 0),
114 ('l', -70000000, '\373\323\342\200', '\200\342\323\373', 0),
115 ('L', 70000000L, '\004,\035\200', '\200\035,\004', 0),
116 ('L', 0x100000000L-70000000, '\373\323\342\200', '\200\342\323\373', 0),
Guido van Rossum420c11c1997-01-03 00:09:46 +0000117 ('f', 2.0, '@\000\000\000', '\000\000\000@', 0),
118 ('d', 2.0, '@\000\000\000\000\000\000\000',
119 '\000\000\000\000\000\000\000@', 0),
120 ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0),
121 ('d', -2.0, '\300\000\000\000\000\000\000\000',
122 '\000\000\000\000\000\000\000\300', 0),
Guido van Rossum2a378501996-12-31 17:25:47 +0000123]
124
Guido van Rossum2a378501996-12-31 17:25:47 +0000125for fmt, arg, big, lil, asy in tests:
126 if verbose:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000127 print "%r %r %r %r" % (fmt, arg, big, lil)
Guido van Rossum2a378501996-12-31 17:25:47 +0000128 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
Tim Peters17e17d42001-06-13 22:45:27 +0000129 ('='+fmt, ISBIGENDIAN and big or lil)]:
Guido van Rossum41360a41998-03-26 19:42:58 +0000130 res = struct.pack(xfmt, arg)
131 if res != exp:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000132 raise TestFailed, "pack(%r, %r) -> %r # expected %r" % (
133 fmt, arg, res, exp)
Guido van Rossum41360a41998-03-26 19:42:58 +0000134 n = struct.calcsize(xfmt)
135 if n != len(res):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000136 raise TestFailed, "calcsize(%r) -> %d # expected %d" % (
137 xfmt, n, len(res))
Guido van Rossum41360a41998-03-26 19:42:58 +0000138 rev = struct.unpack(xfmt, res)[0]
139 if rev != arg and not asy:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000140 raise TestFailed, "unpack(%r, %r) -> (%r,) # expected (%r,)" % (
141 fmt, res, rev, arg)
Tim Peters7b9542a2001-06-10 23:40:19 +0000142
Tim Peters7a3bfc32001-06-12 01:22:22 +0000143###########################################################################
Tim Peters17e17d42001-06-13 22:45:27 +0000144# Simple native q/Q tests.
Tim Peters7b9542a2001-06-10 23:40:19 +0000145
146has_native_qQ = 1
147try:
148 struct.pack("q", 5)
149except struct.error:
150 has_native_qQ = 0
151
152if verbose:
153 print "Platform has native q/Q?", has_native_qQ and "Yes." or "No."
154
Tim Peters7a3bfc32001-06-12 01:22:22 +0000155any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
Tim Peters7b9542a2001-06-10 23:40:19 +0000156simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
157simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
158
Tim Peters7a3bfc32001-06-12 01:22:22 +0000159def test_native_qQ():
Tim Peters7b9542a2001-06-10 23:40:19 +0000160 bytes = struct.calcsize('q')
161 # The expected values here are in big-endian format, primarily because
162 # I'm on a little-endian machine and so this is the clearest way (for
163 # me) to force the code to get exercised.
164 for format, input, expected in (
165 ('q', -1, '\xff' * bytes),
166 ('q', 0, '\x00' * bytes),
167 ('Q', 0, '\x00' * bytes),
168 ('q', 1L, '\x00' * (bytes-1) + '\x01'),
169 ('Q', (1L << (8*bytes))-1, '\xff' * bytes),
170 ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))):
171 got = struct.pack(format, input)
Tim Petersc533edc2001-06-10 23:52:59 +0000172 native_expected = bigendian_to_native(expected)
173 verify(got == native_expected,
Tim Peters7b9542a2001-06-10 23:40:19 +0000174 "%r-pack of %r gave %r, not %r" %
Tim Petersc533edc2001-06-10 23:52:59 +0000175 (format, input, got, native_expected))
Tim Peters7b9542a2001-06-10 23:40:19 +0000176 retrieved = struct.unpack(format, got)[0]
177 verify(retrieved == input,
178 "%r-unpack of %r gave %r, not %r" %
179 (format, got, retrieved, input))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000180
181if has_native_qQ:
182 test_native_qQ()
183
Tim Peters17e17d42001-06-13 22:45:27 +0000184###########################################################################
185# Standard integer tests (bBhHiIlLqQ).
Tim Peters7a3bfc32001-06-12 01:22:22 +0000186
187import binascii
Tim Peters7a3bfc32001-06-12 01:22:22 +0000188
Tim Peters17e17d42001-06-13 22:45:27 +0000189class IntTester:
Tim Peters7a3bfc32001-06-12 01:22:22 +0000190
Tim Peters17e17d42001-06-13 22:45:27 +0000191 # XXX Most std integer modes fail to test for out-of-range.
Tim Peters3eec38a2001-06-18 22:27:39 +0000192 # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
193 # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C
194 # reported by Mark Favas).
195 BUGGY_RANGE_CHECK = "bBhHiIlL"
Tim Peters7a3bfc32001-06-12 01:22:22 +0000196
Tim Peters17e17d42001-06-13 22:45:27 +0000197 def __init__(self, formatpair, bytesize):
198 assert len(formatpair) == 2
199 self.formatpair = formatpair
200 for direction in "<>!=":
201 for code in formatpair:
202 format = direction + code
203 verify(struct.calcsize(format) == bytesize)
204 self.bytesize = bytesize
205 self.bitsize = bytesize * 8
206 self.signed_code, self.unsigned_code = formatpair
207 self.unsigned_min = 0
208 self.unsigned_max = 2L**self.bitsize - 1
209 self.signed_min = -(2L**(self.bitsize-1))
210 self.signed_max = 2L**(self.bitsize-1) - 1
Tim Peters7a3bfc32001-06-12 01:22:22 +0000211
Tim Peters17e17d42001-06-13 22:45:27 +0000212 def test_one(self, x, pack=struct.pack,
213 unpack=struct.unpack,
214 unhexlify=binascii.unhexlify):
215 if verbose:
216 print "trying std", self.formatpair, "on", x, "==", hex(x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000217
Tim Peters17e17d42001-06-13 22:45:27 +0000218 # Try signed.
219 code = self.signed_code
220 if self.signed_min <= x <= self.signed_max:
221 # Try big-endian.
222 expected = long(x)
223 if x < 0:
224 expected += 1L << self.bitsize
225 assert expected > 0
226 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
227 if len(expected) & 1:
228 expected = "0" + expected
229 expected = unhexlify(expected)
230 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000231
Tim Peters17e17d42001-06-13 22:45:27 +0000232 # Pack work?
233 format = ">" + code
234 got = pack(format, x)
235 verify(got == expected,
236 "'%s'-pack of %r gave %r, not %r" %
237 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000238
Tim Peters17e17d42001-06-13 22:45:27 +0000239 # Unpack work?
240 retrieved = unpack(format, got)[0]
241 verify(x == retrieved,
242 "'%s'-unpack of %r gave %r, not %r" %
243 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000244
Tim Peters17e17d42001-06-13 22:45:27 +0000245 # Adding any byte should cause a "too big" error.
246 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000247
Tim Peters17e17d42001-06-13 22:45:27 +0000248 # Try little-endian.
249 format = "<" + code
250 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000251
Tim Peters17e17d42001-06-13 22:45:27 +0000252 # Pack work?
253 got = pack(format, x)
254 verify(got == expected,
255 "'%s'-pack of %r gave %r, not %r" %
256 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000257
Tim Peters17e17d42001-06-13 22:45:27 +0000258 # Unpack work?
259 retrieved = unpack(format, got)[0]
260 verify(x == retrieved,
261 "'%s'-unpack of %r gave %r, not %r" %
262 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000263
Tim Peters17e17d42001-06-13 22:45:27 +0000264 # Adding any byte should cause a "too big" error.
265 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000266
Tim Peters17e17d42001-06-13 22:45:27 +0000267 else:
268 # x is out of range -- verify pack realizes that.
269 if code in self.BUGGY_RANGE_CHECK:
270 if verbose:
271 print "Skipping buggy range check for code", code
272 else:
273 any_err(pack, ">" + code, x)
274 any_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000275
Tim Peters17e17d42001-06-13 22:45:27 +0000276 # Much the same for unsigned.
277 code = self.unsigned_code
278 if self.unsigned_min <= x <= self.unsigned_max:
279 # Try big-endian.
280 format = ">" + code
281 expected = long(x)
282 expected = hex(expected)[2:-1] # chop "0x" and trailing 'L'
283 if len(expected) & 1:
284 expected = "0" + expected
285 expected = unhexlify(expected)
286 expected = "\x00" * (self.bytesize - len(expected)) + expected
Tim Peters7a3bfc32001-06-12 01:22:22 +0000287
Tim Peters17e17d42001-06-13 22:45:27 +0000288 # Pack work?
289 got = pack(format, x)
290 verify(got == expected,
291 "'%s'-pack of %r gave %r, not %r" %
292 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000293
Tim Peters17e17d42001-06-13 22:45:27 +0000294 # Unpack work?
295 retrieved = unpack(format, got)[0]
296 verify(x == retrieved,
297 "'%s'-unpack of %r gave %r, not %r" %
298 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000299
Tim Peters17e17d42001-06-13 22:45:27 +0000300 # Adding any byte should cause a "too big" error.
301 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000302
Tim Peters17e17d42001-06-13 22:45:27 +0000303 # Try little-endian.
304 format = "<" + code
305 expected = string_reverse(expected)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000306
Tim Peters17e17d42001-06-13 22:45:27 +0000307 # Pack work?
308 got = pack(format, x)
309 verify(got == expected,
310 "'%s'-pack of %r gave %r, not %r" %
311 (format, x, got, expected))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000312
Tim Peters17e17d42001-06-13 22:45:27 +0000313 # Unpack work?
314 retrieved = unpack(format, got)[0]
315 verify(x == retrieved,
316 "'%s'-unpack of %r gave %r, not %r" %
317 (format, got, retrieved, x))
Tim Peters7a3bfc32001-06-12 01:22:22 +0000318
Tim Peters17e17d42001-06-13 22:45:27 +0000319 # Adding any byte should cause a "too big" error.
320 any_err(unpack, format, '\x01' + got)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000321
Tim Peters17e17d42001-06-13 22:45:27 +0000322 else:
323 # x is out of range -- verify pack realizes that.
324 if code in self.BUGGY_RANGE_CHECK:
325 if verbose:
326 print "Skipping buggy range check for code", code
327 else:
328 any_err(pack, ">" + code, x)
329 any_err(pack, "<" + code, x)
Tim Peters7a3bfc32001-06-12 01:22:22 +0000330
Tim Peters17e17d42001-06-13 22:45:27 +0000331 def run(self):
332 from random import randrange
333
334 # Create all interesting powers of 2.
335 values = []
336 for exp in range(self.bitsize + 3):
337 values.append(1L << exp)
338
339 # Add some random values.
340 for i in range(self.bitsize):
341 val = 0L
342 for j in range(self.bytesize):
343 val = (val << 8) | randrange(256)
344 values.append(val)
345
346 # Try all those, and their negations, and +-1 from them. Note
347 # that this tests all power-of-2 boundaries in range, and a few out
348 # of range, plus +-(2**n +- 1).
349 for base in values:
350 for val in -base, base:
351 for incr in -1, 0, 1:
352 x = val + incr
353 try:
354 x = int(x)
355 except OverflowError:
356 pass
357 self.test_one(x)
358
359 # Some error cases.
360 for direction in "<>":
361 for code in self.formatpair:
362 for badobject in "a string", 3+42j, randrange:
363 any_err(struct.pack, direction + code, badobject)
364
365for args in [("bB", 1),
366 ("hH", 2),
367 ("iI", 4),
368 ("lL", 4),
369 ("qQ", 8)]:
370 t = IntTester(*args)
371 t.run()
Tim Peters0891ac02001-09-15 02:35:15 +0000372
373
374###########################################################################
375# The p ("Pascal string") code.
376
377def test_p_code():
378 for code, input, expected, expectedback in [
379 ('p','abc', '\x00', ''),
380 ('1p', 'abc', '\x00', ''),
381 ('2p', 'abc', '\x01a', 'a'),
382 ('3p', 'abc', '\x02ab', 'ab'),
383 ('4p', 'abc', '\x03abc', 'abc'),
384 ('5p', 'abc', '\x03abc\x00', 'abc'),
385 ('6p', 'abc', '\x03abc\x00\x00', 'abc'),
386 ('1000p', 'x'*1000, '\xff' + 'x'*999, 'x'*255)]:
387 got = struct.pack(code, input)
388 if got != expected:
389 raise TestFailed("pack(%r, %r) == %r but expected %r" %
390 (code, input, got, expected))
391 (got,) = struct.unpack(code, got)
392 if got != expectedback:
393 raise TestFailed("unpack(%r, %r) == %r but expected %r" %
394 (code, input, got, expectedback))
395
396test_p_code()
Tim Petersd50ade62003-03-20 18:32:13 +0000397
398
399###########################################################################
400# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
401# from the low-order discarded bits could propagate into the exponent
402# field, causing the result to be wrong by a factor of 2.
403
404def test_705836():
405 import math
406
407 for base in range(1, 33):
408 # smaller <- largest representable float less than base.
409 delta = 0.5
410 while base - delta / 2.0 != base:
411 delta /= 2.0
412 smaller = base - delta
413 # Packing this rounds away a solid string of trailing 1 bits.
414 packed = struct.pack("<f", smaller)
415 unpacked = struct.unpack("<f", packed)[0]
416 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
417 # 16, respectively.
418 verify(base == unpacked)
419 bigpacked = struct.pack(">f", smaller)
420 verify(bigpacked == string_reverse(packed),
421 ">f pack should be byte-reversal of <f pack")
422 unpacked = struct.unpack(">f", bigpacked)[0]
423 verify(base == unpacked)
424
425 # Largest finite IEEE single.
426 big = (1 << 24) - 1
427 big = math.ldexp(big, 127 - 23)
428 packed = struct.pack(">f", big)
429 unpacked = struct.unpack(">f", packed)[0]
430 verify(big == unpacked)
431
432 # The same, but tack on a 1 bit so it rounds up to infinity.
433 big = (1 << 25) - 1
434 big = math.ldexp(big, 127 - 24)
435 try:
436 packed = struct.pack(">f", big)
437 except OverflowError:
438 pass
439 else:
440 TestFailed("expected OverflowError")
441
442test_705836()
Bob Ippolitoeb621272006-05-24 15:32:06 +0000443
Bob Ippolitoeb621272006-05-24 15:32:06 +0000444def test_1229380():
445 for endian in ('', '>', '<'):
446 for cls in (int, long):
447 for fmt in ('B', 'H', 'I', 'L'):
448 any_err(struct.pack, endian + fmt, cls(-1))
449
450 any_err(struct.pack, endian + 'B', cls(300))
451 any_err(struct.pack, endian + 'H', cls(70000))
452
453 any_err(struct.pack, endian + 'I', sys.maxint * 4L)
454 any_err(struct.pack, endian + 'L', sys.maxint * 4L)
455
456if 0:
457 # TODO: bug #1229380
458 test_1229380()
Martin Blais2856e5f2006-05-26 12:03:27 +0000459
460class PackBufferTestCase(unittest.TestCase):
461 """
462 Test the packing methods that work on buffers.
463 """
464
465 def test_unpack_from( self ):
466 test_string = 'abcd01234'
467 fmt = '4s'
468 s = struct.Struct(fmt)
469 for cls in (str, buffer):
470 data = cls(test_string)
471 self.assertEquals(s.unpack_from(data), ('abcd',))
472 self.assertEquals(s.unpack_from(data, 2), ('cd01',))
473 self.assertEquals(s.unpack_from(data, 4), ('0123',))
474 for i in xrange(6):
475 self.assertEquals(s.unpack_from(data, i), (data[i:i+4],))
476 for i in xrange(6, len(test_string) + 1):
477 simple_err(s.unpack_from, data, i)
478 for cls in (str, buffer):
479 data = cls(test_string)
480 self.assertEquals(struct.unpack_from(fmt, data), ('abcd',))
481 self.assertEquals(struct.unpack_from(fmt, data, 2), ('cd01',))
482 self.assertEquals(struct.unpack_from(fmt, data, 4), ('0123',))
483 for i in xrange(6):
484 self.assertEquals(struct.unpack_from(fmt, data, i),
485 (data[i:i+4],))
486 for i in xrange(6, len(test_string) + 1):
487 simple_err(struct.unpack_from, fmt, data, i)
488
489 def test_pack_to( self ):
490 test_string = 'Reykjavik rocks, eow!'
491 writable_buf = array.array('c', ' '*100)
492 fmt = '21s'
493 s = struct.Struct(fmt)
494
495 # Test without offset
496 s.pack_to(writable_buf, 0, test_string)
497 from_buf = writable_buf.tostring()[:len(test_string)]
498 self.assertEquals(from_buf, test_string)
499
500 # Test with offset.
501 s.pack_to(writable_buf, 10, test_string)
502 from_buf = writable_buf.tostring()[:len(test_string)+10]
503 self.assertEquals(from_buf, (test_string[:10] + test_string))
504
505 # Go beyond boundaries.
506 small_buf = array.array('c', ' '*10)
507 self.assertRaises(struct.error, s.pack_to, small_buf, 0, test_string)
508 self.assertRaises(struct.error, s.pack_to, small_buf, 2, test_string)
509
510def test_main():
511 test.test_support.run_unittest(PackBufferTestCase)
512
513if __name__ == "__main__":
514 test_main()
515