mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
[3.14] gh-142651: make Mock.call_count thread-safe (GH-142656) (#142743)
gh-142651: make `Mock.call_count` thread-safe (GH-142656)
(cherry picked from commit 850f95f6f6)
Co-authored-by: chaope <pengchaoandy@gmail.com>
This commit is contained in:
parent
bf4f508704
commit
f17281741c
3 changed files with 27 additions and 2 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import sys
|
||||
import time
|
||||
import unittest
|
||||
import threading
|
||||
import concurrent.futures
|
||||
|
||||
from test.support import threading_helper
|
||||
from test.support import setswitchinterval, threading_helper
|
||||
from unittest.mock import patch, ThreadingMock
|
||||
|
||||
|
||||
|
|
@ -196,6 +198,26 @@ def test_reset_mock_resets_wait(self):
|
|||
m.wait_until_any_call_with()
|
||||
m.assert_called_once()
|
||||
|
||||
def test_call_count_thread_safe(self):
|
||||
# See https://github.com/python/cpython/issues/142651.
|
||||
m = ThreadingMock()
|
||||
LOOPS = 100
|
||||
THREADS = 10
|
||||
def test_function():
|
||||
for _ in range(LOOPS):
|
||||
m()
|
||||
|
||||
oldswitchinterval = sys.getswitchinterval()
|
||||
setswitchinterval(1e-6)
|
||||
try:
|
||||
threads = [threading.Thread(target=test_function) for _ in range(THREADS)]
|
||||
with threading_helper.start_threads(threads):
|
||||
pass
|
||||
finally:
|
||||
sys.setswitchinterval(oldswitchinterval)
|
||||
|
||||
self.assertEqual(m.call_count, LOOPS * THREADS)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -1180,7 +1180,6 @@ def _mock_call(self, /, *args, **kwargs):
|
|||
|
||||
def _increment_mock_call(self, /, *args, **kwargs):
|
||||
self.called = True
|
||||
self.call_count += 1
|
||||
|
||||
# handle call_args
|
||||
# needs to be set here so assertions on call arguments pass before
|
||||
|
|
@ -1188,6 +1187,7 @@ def _increment_mock_call(self, /, *args, **kwargs):
|
|||
_call = _Call((args, kwargs), two=True)
|
||||
self.call_args = _call
|
||||
self.call_args_list.append(_call)
|
||||
self.call_count = len(self.call_args_list)
|
||||
|
||||
# initial stuff for method_calls:
|
||||
do_method_calls = self._mock_parent is not None
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
:mod:`unittest.mock`: fix a thread safety issue where :attr:`Mock.call_count
|
||||
<unittest.mock.Mock.call_count>` may return inaccurate values when the mock
|
||||
is called concurrently from multiple threads.
|
||||
Loading…
Add table
Add a link
Reference in a new issue