Files
kefu/wechat_rpa/test_send_lock_initialization.py
T
2026-09-21 10:34:06 +08:00

54 lines
2.2 KiB
Python

"""No live sender locks or desktop operations are used by these tests."""
import ctypes
from ctypes import wintypes
import threading
import types
import unittest
from unittest import mock
import send_lock
@unittest.skipUnless(hasattr(ctypes, 'windll'), 'Windows ctypes signatures')
class SendLockInitializationTests(unittest.TestCase):
def test_concurrent_initialization_publishes_only_finished_backend(self):
entered, allow = threading.Event(), threading.Event()
handle = (1 << 40) + 123
def create(*args):
entered.set()
self.assertTrue(allow.wait(3))
return handle
kernel = types.SimpleNamespace(CreateMutexW=mock.Mock(side_effect=create),
WaitForSingleObject=mock.Mock(return_value=0),
ReleaseMutex=mock.Mock(return_value=True))
results = []
with mock.patch.object(send_lock, '_init_done', False), mock.patch.object(send_lock, '_handle', None), \
mock.patch.object(ctypes.windll, 'kernel32', kernel):
first = threading.Thread(target=lambda: results.append(send_lock._windows_mutex_available()))
second = threading.Thread(target=lambda: results.append(send_lock._windows_mutex_available()))
first.start()
self.assertTrue(entered.wait(3))
second.start()
self.assertFalse(send_lock._init_done)
allow.set()
first.join(3)
second.join(3)
self.assertFalse(first.is_alive() or second.is_alive())
self.assertEqual(results, [True, True])
self.assertEqual(send_lock._handle, handle)
kernel.CreateMutexW.assert_called_once()
self.assertIs(kernel.CreateMutexW.restype, wintypes.HANDLE)
self.assertEqual(kernel.WaitForSingleObject.argtypes, [wintypes.HANDLE, wintypes.DWORD])
def test_unowned_release_cannot_release_mutex(self):
with mock.patch.object(send_lock, '_holder_tid', None), \
mock.patch.object(send_lock, '_windows_mutex_available') as available:
send_lock.release()
available.assert_not_called()
if __name__ == '__main__':
unittest.main()