mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
closes issue29167: fix race condition in (Int)Flag
This commit is contained in:
parent
3831b0a066
commit
28cf663ff0
2 changed files with 99 additions and 6 deletions
|
@ -7,6 +7,11 @@ from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
|
|||
from io import StringIO
|
||||
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
|
||||
from test import support
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
threading = None
|
||||
|
||||
|
||||
# for pickle tests
|
||||
try:
|
||||
|
@ -1983,6 +1988,45 @@ class TestFlag(unittest.TestCase):
|
|||
d = 6
|
||||
self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
|
||||
|
||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||
@support.reap_threads
|
||||
def test_unique_composite(self):
|
||||
# override __eq__ to be identity only
|
||||
class TestFlag(Flag):
|
||||
one = auto()
|
||||
two = auto()
|
||||
three = auto()
|
||||
four = auto()
|
||||
five = auto()
|
||||
six = auto()
|
||||
seven = auto()
|
||||
eight = auto()
|
||||
def __eq__(self, other):
|
||||
return self is other
|
||||
def __hash__(self):
|
||||
return hash(self._value_)
|
||||
# have multiple threads competing to complete the composite members
|
||||
seen = set()
|
||||
failed = False
|
||||
def cycle_enum():
|
||||
nonlocal failed
|
||||
try:
|
||||
for i in range(256):
|
||||
seen.add(TestFlag(i))
|
||||
except Exception:
|
||||
failed = True
|
||||
threads = [
|
||||
threading.Thread(target=cycle_enum)
|
||||
for _ in range(8)
|
||||
]
|
||||
with support.start_threads(threads):
|
||||
pass
|
||||
# check that only 248 members were created
|
||||
self.assertFalse(
|
||||
failed,
|
||||
'at least one thread failed while creating composite members')
|
||||
self.assertEqual(256, len(seen), 'too many composite members created')
|
||||
|
||||
|
||||
class TestIntFlag(unittest.TestCase):
|
||||
"""Tests of the IntFlags."""
|
||||
|
@ -2275,6 +2319,46 @@ class TestIntFlag(unittest.TestCase):
|
|||
for f in Open:
|
||||
self.assertEqual(bool(f.value), bool(f))
|
||||
|
||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||
@support.reap_threads
|
||||
def test_unique_composite(self):
|
||||
# override __eq__ to be identity only
|
||||
class TestFlag(IntFlag):
|
||||
one = auto()
|
||||
two = auto()
|
||||
three = auto()
|
||||
four = auto()
|
||||
five = auto()
|
||||
six = auto()
|
||||
seven = auto()
|
||||
eight = auto()
|
||||
def __eq__(self, other):
|
||||
return self is other
|
||||
def __hash__(self):
|
||||
return hash(self._value_)
|
||||
# have multiple threads competing to complete the composite members
|
||||
seen = set()
|
||||
failed = False
|
||||
def cycle_enum():
|
||||
nonlocal failed
|
||||
try:
|
||||
for i in range(256):
|
||||
seen.add(TestFlag(i))
|
||||
except Exception:
|
||||
failed = True
|
||||
threads = [
|
||||
threading.Thread(target=cycle_enum)
|
||||
for _ in range(8)
|
||||
]
|
||||
with support.start_threads(threads):
|
||||
pass
|
||||
# check that only 248 members were created
|
||||
self.assertFalse(
|
||||
failed,
|
||||
'at least one thread failed while creating composite members')
|
||||
self.assertEqual(256, len(seen), 'too many composite members created')
|
||||
|
||||
|
||||
class TestUnique(unittest.TestCase):
|
||||
|
||||
def test_unique_clean(self):
|
||||
|
@ -2484,7 +2568,8 @@ CONVERT_TEST_NAME_F = 5
|
|||
class TestIntEnumConvert(unittest.TestCase):
|
||||
def test_convert_value_lookup_priority(self):
|
||||
test_type = enum.IntEnum._convert(
|
||||
'UnittestConvert', 'test.test_enum',
|
||||
'UnittestConvert',
|
||||
('test.test_enum', '__main__')[__name__=='__main__'],
|
||||
filter=lambda x: x.startswith('CONVERT_TEST_'))
|
||||
# We don't want the reverse lookup value to vary when there are
|
||||
# multiple possible names for a given value. It should always
|
||||
|
@ -2493,7 +2578,8 @@ class TestIntEnumConvert(unittest.TestCase):
|
|||
|
||||
def test_convert(self):
|
||||
test_type = enum.IntEnum._convert(
|
||||
'UnittestConvert', 'test.test_enum',
|
||||
'UnittestConvert',
|
||||
('test.test_enum', '__main__')[__name__=='__main__'],
|
||||
filter=lambda x: x.startswith('CONVERT_TEST_'))
|
||||
# Ensure that test_type has all of the desired names and values.
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_F,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue