summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_code.py
diff options
context:
space:
mode:
authorDennis Sweeney <36520290+sweeneyde@users.noreply.github.com>2022-12-23 18:15:47 (GMT)
committerGitHub <noreply@github.com>2022-12-23 18:15:47 (GMT)
commita98d9ea56e7b473af54438ecc487a6bf1b4d6530 (patch)
tree792d718b70d08874bd011cbf800af000abdca7e9 /Lib/test/test_code.py
parent36d358348de8efad75ebcf55dad8ed4a4f6dcda9 (diff)
downloadcpython-a98d9ea56e7b473af54438ecc487a6bf1b4d6530.zip
cpython-a98d9ea56e7b473af54438ecc487a6bf1b4d6530.tar.gz
cpython-a98d9ea56e7b473af54438ecc487a6bf1b4d6530.tar.bz2
gh-94155: Reduce hash collisions for code objects (#100183)
* Uses a better hashing algorithm to get better dispersion and remove commutativity. * Incorporates `co_firstlineno`, `Py_SIZE(co)`, and bytecode instructions. * This is now the entire set of criteria used in `code_richcompare`, except for `_PyCode_ConstantKey` (which would incorporate the types of `co_consts` rather than just their values).
Diffstat (limited to 'Lib/test/test_code.py')
-rw-r--r--Lib/test/test_code.py26
1 files changed, 26 insertions, 0 deletions
diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
index 02ab8fb..b13d577 100644
--- a/Lib/test/test_code.py
+++ b/Lib/test/test_code.py
@@ -465,6 +465,32 @@ class CodeTest(unittest.TestCase):
self.assertNotEqual(code_b, code_d)
self.assertNotEqual(code_c, code_d)
+ def test_code_hash_uses_firstlineno(self):
+ c1 = (lambda: 1).__code__
+ c2 = (lambda: 1).__code__
+ self.assertNotEqual(c1, c2)
+ self.assertNotEqual(hash(c1), hash(c2))
+ c3 = c1.replace(co_firstlineno=17)
+ self.assertNotEqual(c1, c3)
+ self.assertNotEqual(hash(c1), hash(c3))
+
+ def test_code_hash_uses_order(self):
+ # Swapping posonlyargcount and kwonlyargcount should change the hash.
+ c = (lambda x, y, *, z=1, w=1: 1).__code__
+ self.assertEqual(c.co_argcount, 2)
+ self.assertEqual(c.co_posonlyargcount, 0)
+ self.assertEqual(c.co_kwonlyargcount, 2)
+ swapped = c.replace(co_posonlyargcount=2, co_kwonlyargcount=0)
+ self.assertNotEqual(c, swapped)
+ self.assertNotEqual(hash(c), hash(swapped))
+
+ def test_code_hash_uses_bytecode(self):
+ c = (lambda x, y: x + y).__code__
+ d = (lambda x, y: x * y).__code__
+ c1 = c.replace(co_code=d.co_code)
+ self.assertNotEqual(c, c1)
+ self.assertNotEqual(hash(c), hash(c1))
+
def isinterned(s):
return s is sys.intern(('_' + s + '_')[1:-1])