From 1f7a1fa77e46b53001478ccfd6219b5cbe794c86 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Thu, 11 Mar 2021 15:54:34 -0700 Subject: [PATCH] bpo-43132: Add tests for find_in_strong_cache() bug in _zoneinfo Co-Authored-By: Paul Ganssle --- Lib/test/test_zoneinfo/test_zoneinfo.py | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index a9375fd55857bc..10adb9ca881b46 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -400,6 +400,20 @@ def test_time_fixed_offset(self): self.assertEqual(t.utcoffset(), offset.utcoffset) self.assertEqual(t.dst(), offset.dst) + def test_cache_exception(self): + class ComparisonError(Exception): + pass + + class Incomparable(str): + def __eq__(self, other): + raise ComparisonError + def __hash__(self): + return id(self) + + key = Incomparable("America/Los_Angeles") + with self.assertRaises(ComparisonError): + self.klass(key) + class CZoneInfoTest(ZoneInfoTest): module = c_zoneinfo @@ -1377,6 +1391,33 @@ def test_clear_cache_two_keys(self): self.assertIsNot(dub0, dub1) self.assertIs(tok0, tok1) + def test_clear_cache_refleak(self): + class ComparisonError(Exception): + pass + + class Stringy(str): + def __new__(cls, value): + rv = super().__new__(cls, value) + rv.allow_comparisons = True + return rv + def __eq__(self, other): + if not self.allow_comparisons: + raise ComparisonError + return super().__eq__(other) + def __hash__(self): + return hash(self[:]) + + key = Stringy("America/Los_Angeles") + self.klass(key) + key.allow_comparisons = False + try: + # Note: This is try/except rather than assertRaises because + # there is no guarantee that the key is even still in the cache, + # or that the key for the cache is the original `key` object. + self.klass.clear_cache(only_keys="America/Los_Angeles") + except ComparisonError: + pass + class CZoneInfoCacheTest(ZoneInfoCacheTest): module = c_zoneinfo