gh-87298: Add tests for find_in_strong_cache() bug in _zoneinfo (GH-24829)

Co-authored-by: Paul Ganssle <p.ganssle@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Zackery Spytz 2025-07-01 07:55:24 -07:00 committed by GitHub
parent 9c0cb5beb8
commit 12ce16bc13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -58,6 +58,10 @@ def tearDownModule():
shutil.rmtree(TEMP_DIR)
class CustomError(Exception):
pass
class TzPathUserMixin:
"""
Adds a setUp() and tearDown() to make TZPATH manipulations thread-safe.
@ -404,6 +408,25 @@ class ZoneInfoTest(TzPathUserMixin, ZoneInfoTestBase):
self.assertEqual(t.utcoffset(), offset.utcoffset)
self.assertEqual(t.dst(), offset.dst)
def test_cache_exception(self):
class Incomparable(str):
eq_called = False
def __eq__(self, other):
self.eq_called = True
raise CustomError
__hash__ = str.__hash__
key = "America/Los_Angeles"
tz1 = self.klass(key)
key = Incomparable(key)
try:
tz2 = self.klass(key)
except CustomError:
self.assertTrue(key.eq_called)
else:
self.assertFalse(key.eq_called)
self.assertIs(tz2, tz1)
class CZoneInfoTest(ZoneInfoTest):
module = c_zoneinfo
@ -1507,6 +1530,26 @@ class ZoneInfoCacheTest(TzPathUserMixin, ZoneInfoTestBase):
self.assertIsNot(dub0, dub1)
self.assertIs(tok0, tok1)
def test_clear_cache_refleak(self):
class Stringy(str):
allow_comparisons = True
def __eq__(self, other):
if not self.allow_comparisons:
raise CustomError
return super().__eq__(other)
__hash__ = str.__hash__
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 CustomError:
pass
class CZoneInfoCacheTest(ZoneInfoCacheTest):
module = c_zoneinfo