diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2019-01-26 08:02:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-26 08:02:00 (GMT) |
commit | d8080c01195cc9a19af752bfa04d98824dd9fb15 (patch) | |
tree | 75ab01426d6a329ad2987f58b5261443a0ee7c0e /Lib/test | |
parent | adad9e68013aac166c84ffe4e23f3a5464f41840 (diff) | |
download | cpython-d8080c01195cc9a19af752bfa04d98824dd9fb15.zip cpython-d8080c01195cc9a19af752bfa04d98824dd9fb15.tar.gz cpython-d8080c01195cc9a19af752bfa04d98824dd9fb15.tar.bz2 |
bpo-35780: Fix errors in lru_cache() C code (GH-11623)
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_functools.py | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index ffbd0fc..63a9ade 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1233,6 +1233,33 @@ class TestLRU: self.assertEqual(misses, 4) self.assertEqual(currsize, 2) + def test_lru_bug_35780(self): + # C version of the lru_cache was not checking to see if + # the user function call has already modified the cache + # (this arises in recursive calls and in multi-threading). + # This cause the cache to have orphan links not referenced + # by the cache dictionary. + + once = True # Modified by f(x) below + + @self.module.lru_cache(maxsize=10) + def f(x): + nonlocal once + rv = f'.{x}.' + if x == 20 and once: + once = False + rv = f(x) + return rv + + # Fill the cache + for x in range(15): + self.assertEqual(f(x), f'.{x}.') + self.assertEqual(f.cache_info().currsize, 10) + + # Make a recursive call and make sure the cache remains full + self.assertEqual(f(20), '.20.') + self.assertEqual(f.cache_info().currsize, 10) + def test_lru_hash_only_once(self): # To protect against weird reentrancy bugs and to improve # efficiency when faced with slow __hash__ methods, the @@ -1329,7 +1356,7 @@ class TestLRU: for i in (0, 1): self.assertEqual([eq(n) for n in range(150)], list(range(150))) self.assertEqual(eq.cache_info(), - self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) + self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without |