"""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()