mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Generalize the new qQ std-mode tests to all int codes (bBhHiIlLqQ).
Unfortunately, the std-mode bBhHIL codes don't do any range-checking; if and when some of those get fixed, remove their letters from the IntTester.BUGGY_RANGE_CHECK string. In the meantime, a msg saying that range-tests are getting skipped is printed to stdout whenever one is skipped.
This commit is contained in:
		
							parent
							
								
									f251d06a66
								
							
						
					
					
						commit
						17e17d4406
					
				
					 1 changed files with 180 additions and 136 deletions
				
			
		|  | @ -2,6 +2,23 @@ | ||||||
| import struct | import struct | ||||||
| ## import pdb | ## import pdb | ||||||
| 
 | 
 | ||||||
|  | import sys | ||||||
|  | ISBIGENDIAN = sys.byteorder == "big" | ||||||
|  | del sys | ||||||
|  | verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN, | ||||||
|  |        "bigendian determination appears wrong") | ||||||
|  | 
 | ||||||
|  | def string_reverse(s): | ||||||
|  |     chars = list(s) | ||||||
|  |     chars.reverse() | ||||||
|  |     return "".join(chars) | ||||||
|  | 
 | ||||||
|  | def bigendian_to_native(value): | ||||||
|  |     if ISBIGENDIAN: | ||||||
|  |         return value | ||||||
|  |     else: | ||||||
|  |         return string_reverse(value) | ||||||
|  | 
 | ||||||
| def simple_err(func, *args): | def simple_err(func, *args): | ||||||
|     try: |     try: | ||||||
|         apply(func, args) |         apply(func, args) | ||||||
|  | @ -22,6 +39,7 @@ def any_err(func, *args): | ||||||
|             func.__name__, args) |             func.__name__, args) | ||||||
| ##      pdb.set_trace() | ##      pdb.set_trace() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| simple_err(struct.calcsize, 'Z') | simple_err(struct.calcsize, 'Z') | ||||||
| 
 | 
 | ||||||
| sz = struct.calcsize('i') | sz = struct.calcsize('i') | ||||||
|  | @ -103,13 +121,11 @@ def any_err(func, *args): | ||||||
|                '\000\000\000\000\000\000\000\300', 0), |                '\000\000\000\000\000\000\000\300', 0), | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| isbigendian = struct.pack('=i', 1)[0] == chr(0) |  | ||||||
| 
 |  | ||||||
| for fmt, arg, big, lil, asy in tests: | for fmt, arg, big, lil, asy in tests: | ||||||
|     if verbose: |     if verbose: | ||||||
|         print `fmt`, `arg`, `big`, `lil` |         print `fmt`, `arg`, `big`, `lil` | ||||||
|     for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil), |     for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil), | ||||||
|                         ('='+fmt, isbigendian and big or lil)]: |                         ('='+fmt, ISBIGENDIAN and big or lil)]: | ||||||
|         res = struct.pack(xfmt, arg) |         res = struct.pack(xfmt, arg) | ||||||
|         if res != exp: |         if res != exp: | ||||||
|             raise TestFailed, "pack(%s, %s) -> %s # expected %s" % ( |             raise TestFailed, "pack(%s, %s) -> %s # expected %s" % ( | ||||||
|  | @ -124,7 +140,7 @@ def any_err(func, *args): | ||||||
|                 `fmt`, `res`, `rev`, `arg`) |                 `fmt`, `res`, `rev`, `arg`) | ||||||
| 
 | 
 | ||||||
| ########################################################################### | ########################################################################### | ||||||
| # q/Q tests. | # Simple native q/Q tests. | ||||||
| 
 | 
 | ||||||
| has_native_qQ = 1 | has_native_qQ = 1 | ||||||
| try: | try: | ||||||
|  | @ -139,17 +155,6 @@ def any_err(func, *args): | ||||||
| simple_err(struct.pack, "q", "a")  # can't pack string as 'q' regardless | simple_err(struct.pack, "q", "a")  # can't pack string as 'q' regardless | ||||||
| simple_err(struct.pack, "Q", "a")  # ditto, but 'Q' | simple_err(struct.pack, "Q", "a")  # ditto, but 'Q' | ||||||
| 
 | 
 | ||||||
| def string_reverse(s): |  | ||||||
|     chars = list(s) |  | ||||||
|     chars.reverse() |  | ||||||
|     return "".join(chars) |  | ||||||
| 
 |  | ||||||
| def bigendian_to_native(value): |  | ||||||
|     if isbigendian: |  | ||||||
|         return value |  | ||||||
|     else: |  | ||||||
|         return string_reverse(value) |  | ||||||
| 
 |  | ||||||
| def test_native_qQ(): | def test_native_qQ(): | ||||||
|     bytes = struct.calcsize('q') |     bytes = struct.calcsize('q') | ||||||
|     # The expected values here are in big-endian format, primarily because |     # The expected values here are in big-endian format, primarily because | ||||||
|  | @ -175,129 +180,162 @@ def test_native_qQ(): | ||||||
| if has_native_qQ: | if has_native_qQ: | ||||||
|     test_native_qQ() |     test_native_qQ() | ||||||
| 
 | 
 | ||||||
| # Standard q/Q (8 bytes; should work on all platforms). | ########################################################################### | ||||||
| 
 | # Standard integer tests (bBhHiIlLqQ). | ||||||
| MIN_Q, MAX_Q = 0, 2L**64 - 1 |  | ||||||
| MIN_q, MAX_q = -(2L**63), 2L**63 - 1 |  | ||||||
| 
 | 
 | ||||||
| import binascii | import binascii | ||||||
| def test_one_qQ(x, pack=struct.pack, | 
 | ||||||
|  | class IntTester: | ||||||
|  | 
 | ||||||
|  |     # XXX Most std integer modes fail to test for out-of-range. | ||||||
|  |     BUGGY_RANGE_CHECK = "bBhHIL" | ||||||
|  | 
 | ||||||
|  |     def __init__(self, formatpair, bytesize): | ||||||
|  |         assert len(formatpair) == 2 | ||||||
|  |         self.formatpair = formatpair | ||||||
|  |         for direction in "<>!=": | ||||||
|  |             for code in formatpair: | ||||||
|  |                 format = direction + code | ||||||
|  |                 verify(struct.calcsize(format) == bytesize) | ||||||
|  |         self.bytesize = bytesize | ||||||
|  |         self.bitsize = bytesize * 8 | ||||||
|  |         self.signed_code, self.unsigned_code = formatpair | ||||||
|  |         self.unsigned_min = 0 | ||||||
|  |         self.unsigned_max = 2L**self.bitsize - 1 | ||||||
|  |         self.signed_min = -(2L**(self.bitsize-1)) | ||||||
|  |         self.signed_max = 2L**(self.bitsize-1) - 1 | ||||||
|  | 
 | ||||||
|  |     def test_one(self, x, pack=struct.pack, | ||||||
|                           unpack=struct.unpack, |                           unpack=struct.unpack, | ||||||
|                           unhexlify=binascii.unhexlify): |                           unhexlify=binascii.unhexlify): | ||||||
|         if verbose: |         if verbose: | ||||||
|         print "trying std q/Q on", x, "==", hex(x) |             print "trying std", self.formatpair, "on", x, "==", hex(x) | ||||||
| 
 | 
 | ||||||
|     # Try 'q'. |         # Try signed. | ||||||
|     if MIN_q <= x <= MAX_q: |         code = self.signed_code | ||||||
|         # Try '>q'. |         if self.signed_min <= x <= self.signed_max: | ||||||
|  |             # Try big-endian. | ||||||
|             expected = long(x) |             expected = long(x) | ||||||
|             if x < 0: |             if x < 0: | ||||||
|             expected += 1L << 64 |                 expected += 1L << self.bitsize | ||||||
|                 assert expected > 0 |                 assert expected > 0 | ||||||
|             expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' |             expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' | ||||||
|             if len(expected) & 1: |             if len(expected) & 1: | ||||||
|                 expected = "0" + expected |                 expected = "0" + expected | ||||||
|             expected = unhexlify(expected) |             expected = unhexlify(expected) | ||||||
|         expected = "\x00" * (8 - len(expected)) + expected |             expected = "\x00" * (self.bytesize - len(expected)) + expected | ||||||
| 
 | 
 | ||||||
|         # >q pack work? |             # Pack work? | ||||||
|         got = pack(">q", x) |             format = ">" + code | ||||||
|  |             got = pack(format, x) | ||||||
|             verify(got == expected, |             verify(got == expected, | ||||||
|                "'>q'-pack of %r gave %r, not %r" % |                    "'%s'-pack of %r gave %r, not %r" % | ||||||
|                 (x, got, expected)) |                     (format, x, got, expected)) | ||||||
| 
 | 
 | ||||||
|         # >q unpack work? |             # Unpack work? | ||||||
|         retrieved = unpack(">q", got)[0] |             retrieved = unpack(format, got)[0] | ||||||
|             verify(x == retrieved, |             verify(x == retrieved, | ||||||
|                "'>q'-unpack of %r gave %r, not %r" % |                    "'%s'-unpack of %r gave %r, not %r" % | ||||||
|                 (got, retrieved, x)) |                     (format, got, retrieved, x)) | ||||||
| 
 | 
 | ||||||
|             # Adding any byte should cause a "too big" error. |             # Adding any byte should cause a "too big" error. | ||||||
|         any_err(unpack, ">q", '\x01' + got) |             any_err(unpack, format, '\x01' + got) | ||||||
| 
 | 
 | ||||||
|         # Try '<q'. |             # Try little-endian. | ||||||
|  |             format = "<" + code | ||||||
|             expected = string_reverse(expected) |             expected = string_reverse(expected) | ||||||
| 
 | 
 | ||||||
|         # <q pack work? |             # Pack work? | ||||||
|         got = pack("<q", x) |             got = pack(format, x) | ||||||
|             verify(got == expected, |             verify(got == expected, | ||||||
|                "'<q'-pack of %r gave %r, not %r" % |                    "'%s'-pack of %r gave %r, not %r" % | ||||||
|                 (x, got, expected)) |                     (format, x, got, expected)) | ||||||
| 
 | 
 | ||||||
|         # <q unpack work? |             # Unpack work? | ||||||
|         retrieved = unpack("<q", got)[0] |             retrieved = unpack(format, got)[0] | ||||||
|             verify(x == retrieved, |             verify(x == retrieved, | ||||||
|                "'<q'-unpack of %r gave %r, not %r" % |                    "'%s'-unpack of %r gave %r, not %r" % | ||||||
|                 (got, retrieved, x)) |                     (format, got, retrieved, x)) | ||||||
| 
 | 
 | ||||||
|             # Adding any byte should cause a "too big" error. |             # Adding any byte should cause a "too big" error. | ||||||
|         any_err(unpack, "<q", '\x01' + got) |             any_err(unpack, format, '\x01' + got) | ||||||
| 
 | 
 | ||||||
|         else: |         else: | ||||||
|         # x is out of q's range -- verify pack realizes that. |             # x is out of range -- verify pack realizes that. | ||||||
|         any_err(pack, '>q', x) |             if code in self.BUGGY_RANGE_CHECK: | ||||||
|         any_err(pack, '<q', x) |                 if verbose: | ||||||
|  |                     print "Skipping buggy range check for code", code | ||||||
|  |             else: | ||||||
|  |                 any_err(pack, ">" + code, x) | ||||||
|  |                 any_err(pack, "<" + code, x) | ||||||
| 
 | 
 | ||||||
|     # Much the same for 'Q'. |         # Much the same for unsigned. | ||||||
|     if MIN_Q <= x <= MAX_Q: |         code = self.unsigned_code | ||||||
|         # Try '>Q'. |         if self.unsigned_min <= x <= self.unsigned_max: | ||||||
|  |             # Try big-endian. | ||||||
|  |             format = ">" + code | ||||||
|             expected = long(x) |             expected = long(x) | ||||||
|             expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' |             expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' | ||||||
|             if len(expected) & 1: |             if len(expected) & 1: | ||||||
|                 expected = "0" + expected |                 expected = "0" + expected | ||||||
|             expected = unhexlify(expected) |             expected = unhexlify(expected) | ||||||
|         expected = "\x00" * (8 - len(expected)) + expected |             expected = "\x00" * (self.bytesize - len(expected)) + expected | ||||||
| 
 | 
 | ||||||
|         # >Q pack work? |             # Pack work? | ||||||
|         got = pack(">Q", x) |             got = pack(format, x) | ||||||
|             verify(got == expected, |             verify(got == expected, | ||||||
|                "'>Q'-pack of %r gave %r, not %r" % |                    "'%s'-pack of %r gave %r, not %r" % | ||||||
|                 (x, got, expected)) |                     (format, x, got, expected)) | ||||||
| 
 | 
 | ||||||
|         # >Q unpack work? |             # Unpack work? | ||||||
|         retrieved = unpack(">Q", got)[0] |             retrieved = unpack(format, got)[0] | ||||||
|             verify(x == retrieved, |             verify(x == retrieved, | ||||||
|                "'>Q'-unpack of %r gave %r, not %r" % |                    "'%s'-unpack of %r gave %r, not %r" % | ||||||
|                 (got, retrieved, x)) |                     (format, got, retrieved, x)) | ||||||
| 
 | 
 | ||||||
|             # Adding any byte should cause a "too big" error. |             # Adding any byte should cause a "too big" error. | ||||||
|         any_err(unpack, ">Q", '\x01' + got) |             any_err(unpack, format, '\x01' + got) | ||||||
| 
 | 
 | ||||||
|         # Try '<Q'. |             # Try little-endian. | ||||||
|  |             format = "<" + code | ||||||
|             expected = string_reverse(expected) |             expected = string_reverse(expected) | ||||||
| 
 | 
 | ||||||
|         # <Q pack work? |             # Pack work? | ||||||
|         got = pack("<Q", x) |             got = pack(format, x) | ||||||
|             verify(got == expected, |             verify(got == expected, | ||||||
|                "'<Q'-pack of %r gave %r, not %r" % |                    "'%s'-pack of %r gave %r, not %r" % | ||||||
|                 (x, got, expected)) |                     (format, x, got, expected)) | ||||||
| 
 | 
 | ||||||
|         # <Q unpack work? |             # Unpack work? | ||||||
|         retrieved = unpack("<Q", got)[0] |             retrieved = unpack(format, got)[0] | ||||||
|             verify(x == retrieved, |             verify(x == retrieved, | ||||||
|                "'<Q'-unpack of %r gave %r, not %r" % |                    "'%s'-unpack of %r gave %r, not %r" % | ||||||
|                 (got, retrieved, x)) |                     (format, got, retrieved, x)) | ||||||
| 
 | 
 | ||||||
|             # Adding any byte should cause a "too big" error. |             # Adding any byte should cause a "too big" error. | ||||||
|         any_err(unpack, "<Q", '\x01' + got) |             any_err(unpack, format, '\x01' + got) | ||||||
| 
 | 
 | ||||||
|         else: |         else: | ||||||
|         # x is out of Q's range -- verify pack realizes that. |             # x is out of range -- verify pack realizes that. | ||||||
|         any_err(pack, '>Q', x) |             if code in self.BUGGY_RANGE_CHECK: | ||||||
|         any_err(pack, '<Q', x) |                 if verbose: | ||||||
|  |                     print "Skipping buggy range check for code", code | ||||||
|  |             else: | ||||||
|  |                 any_err(pack, ">" + code, x) | ||||||
|  |                 any_err(pack, "<" + code, x) | ||||||
| 
 | 
 | ||||||
| def test_std_qQ(): |     def run(self): | ||||||
|         from random import randrange |         from random import randrange | ||||||
| 
 | 
 | ||||||
|         # Create all interesting powers of 2. |         # Create all interesting powers of 2. | ||||||
|         values = [] |         values = [] | ||||||
|     for exp in range(70): |         for exp in range(self.bitsize + 3): | ||||||
|             values.append(1L << exp) |             values.append(1L << exp) | ||||||
| 
 | 
 | ||||||
|     # Add some random 64-bit values. |         # Add some random values. | ||||||
|     for i in range(50): |         for i in range(self.bitsize): | ||||||
|             val = 0L |             val = 0L | ||||||
|         for j in range(8): |             for j in range(self.bytesize): | ||||||
|                 val = (val << 8) | randrange(256) |                 val = (val << 8) | randrange(256) | ||||||
|             values.append(val) |             values.append(val) | ||||||
| 
 | 
 | ||||||
|  | @ -312,12 +350,18 @@ def test_std_qQ(): | ||||||
|                         x = int(x) |                         x = int(x) | ||||||
|                     except OverflowError: |                     except OverflowError: | ||||||
|                         pass |                         pass | ||||||
|                 test_one_qQ(x) |                     self.test_one(x) | ||||||
| 
 | 
 | ||||||
|         # Some error cases. |         # Some error cases. | ||||||
|         for direction in "<>": |         for direction in "<>": | ||||||
|         for letter in "qQ": |             for code in self.formatpair: | ||||||
|                 for badobject in "a string", 3+42j, randrange: |                 for badobject in "a string", 3+42j, randrange: | ||||||
|                 any_err(struct.pack, direction + letter, badobject) |                     any_err(struct.pack, direction + code, badobject) | ||||||
| 
 | 
 | ||||||
| test_std_qQ() | for args in [("bB", 1), | ||||||
|  |              ("hH", 2), | ||||||
|  |              ("iI", 4), | ||||||
|  |              ("lL", 4), | ||||||
|  |              ("qQ", 8)]: | ||||||
|  |     t = IntTester(*args) | ||||||
|  |     t.run() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Peters
						Tim Peters