[pypy-svn] r52676 - in pypy/dist/pypy/module/zlib: . test

arigo at codespeak.net arigo at codespeak.net
Tue Mar 18 10:37:07 CET 2008


Author: arigo
Date: Tue Mar 18 10:37:05 2008
New Revision: 52676

Modified:
   pypy/dist/pypy/module/zlib/interp_zlib.py
   pypy/dist/pypy/module/zlib/test/test_zlib.py
Log:
zlib.crc32() and zlib.adler32() on 64-bit platforms:
follow the newly fixed behavior of CPython 2.6 instead
of the bogus one of previous versions.


Modified: pypy/dist/pypy/module/zlib/interp_zlib.py
==============================================================================
--- pypy/dist/pypy/module/zlib/interp_zlib.py	(original)
+++ pypy/dist/pypy/module/zlib/interp_zlib.py	Tue Mar 18 10:37:05 2008
@@ -9,6 +9,17 @@
 from pypy.rlib import rzlib
 
 
+if intmask(2**31) == -2**31:
+    # 32-bit platforms
+    unsigned_to_signed_32bit = intmask
+else:
+    # 64-bit platforms
+    def unsigned_to_signed_32bit(x):
+        # assumes that 'x' is in range(0, 2**32) to start with
+        SIGN_EXTEND2 = 1 << 31
+        return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
+
+
 def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
     """
     crc32(string[, start]) -- Compute a CRC-32 checksum of string.
@@ -20,9 +31,10 @@
 
     # This is, perhaps, a little stupid.  zlib returns the checksum unsigned.
     # CPython exposes it as a signed value, though. -exarkun
-    # The value *is* unsigned on 64-bit platforms in CPython... bah.
-    # For now let's do the same as CPython and boldly cast to a C long. -arigo
-    checksum = intmask(checksum)
+    # Note that in CPython < 2.6 on 64-bit platforms the result is
+    # actually unsigned, but it was considered to be a bug so we stick to
+    # the 2.6 behavior and always return a number in range(-2**31, 2**31).
+    checksum = unsigned_to_signed_32bit(checksum)
 
     return space.wrap(checksum)
 crc32.unwrap_spec = [ObjSpace, 'bufferstr', int]
@@ -36,12 +48,8 @@
     an integer.
     """
     checksum = rzlib.adler32(string, start)
-
-    # This is, perhaps, a little stupid.  zlib returns the checksum unsigned.
-    # CPython exposes it as a signed value, though. -exarkun
-    # The value *is* unsigned on 64-bit platforms in CPython... bah.
-    # For now let's do the same as CPython and boldly cast to a C long. -arigo
-    checksum = intmask(checksum)
+    # See comments in crc32() for the following line
+    checksum = unsigned_to_signed_32bit(checksum)
 
     return space.wrap(checksum)
 adler32.unwrap_spec = [ObjSpace, 'bufferstr', int]

Modified: pypy/dist/pypy/module/zlib/test/test_zlib.py
==============================================================================
--- pypy/dist/pypy/module/zlib/test/test_zlib.py	(original)
+++ pypy/dist/pypy/module/zlib/test/test_zlib.py	Tue Mar 18 10:37:05 2008
@@ -8,8 +8,15 @@
 except ImportError:
     import py; py.test.skip("no zlib module on this host Python")
 
+from pypy.module.zlib import interp_zlib
 from pypy.conftest import gettestobjspace
 
+def test_unsigned_to_signed_32bit():
+    assert interp_zlib.unsigned_to_signed_32bit(123) == 123
+    assert interp_zlib.unsigned_to_signed_32bit(2**31) == -2**31
+    assert interp_zlib.unsigned_to_signed_32bit(2**32-1) == -1
+
+
 class AppTestZlib(object):
     def setup_class(cls):
         """
@@ -38,7 +45,8 @@
     def test_crc32(self):
         """
         When called with a string, zlib.crc32 should compute its CRC32 and
-        return it as a signed 32 bit integer.
+        return it as a signed 32 bit integer.  On 64-bit machines too
+        (it is a bug in CPython < 2.6 to return unsigned values in this case).
         """
         assert self.zlib.crc32('') == 0
         assert self.zlib.crc32('\0') == -771559539
@@ -64,6 +72,8 @@
         """
         When called with a string, zlib.crc32 should compute its adler 32
         checksum and return it as a signed 32 bit integer.
+        On 64-bit machines too
+        (it is a bug in CPython < 2.6 to return unsigned values in this case).
         """
         assert self.zlib.adler32('') == 1
         assert self.zlib.adler32('\0') == 65537



More information about the Pypy-commit mailing list