54 lines
2.2 KiB
Python
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()
|