/Lib/test/test_asyncio/test_locks.py

https://github.com/akheron/cpython · Python · 921 lines · 684 code · 216 blank · 21 comment · 45 complexity · 265bbe10b227373bcd337b3137b15d01 MD5 · raw file

  1. """Tests for lock.py"""
  2. import unittest
  3. from unittest import mock
  4. import re
  5. import asyncio
  6. from asyncio import test_utils
  7. STR_RGX_REPR = (
  8. r'^<(?P<class>.*?) object at (?P<address>.*?)'
  9. r'\[(?P<extras>'
  10. r'(set|unset|locked|unlocked)(,value:\d)?(,waiters:\d+)?'
  11. r')\]>\Z'
  12. )
  13. RGX_REPR = re.compile(STR_RGX_REPR)
  14. class LockTests(test_utils.TestCase):
  15. def setUp(self):
  16. super().setUp()
  17. self.loop = self.new_test_loop()
  18. def test_ctor_loop(self):
  19. loop = mock.Mock()
  20. lock = asyncio.Lock(loop=loop)
  21. self.assertIs(lock._loop, loop)
  22. lock = asyncio.Lock(loop=self.loop)
  23. self.assertIs(lock._loop, self.loop)
  24. def test_ctor_noloop(self):
  25. asyncio.set_event_loop(self.loop)
  26. lock = asyncio.Lock()
  27. self.assertIs(lock._loop, self.loop)
  28. def test_repr(self):
  29. lock = asyncio.Lock(loop=self.loop)
  30. self.assertTrue(repr(lock).endswith('[unlocked]>'))
  31. self.assertTrue(RGX_REPR.match(repr(lock)))
  32. @asyncio.coroutine
  33. def acquire_lock():
  34. yield from lock
  35. self.loop.run_until_complete(acquire_lock())
  36. self.assertTrue(repr(lock).endswith('[locked]>'))
  37. self.assertTrue(RGX_REPR.match(repr(lock)))
  38. def test_lock(self):
  39. lock = asyncio.Lock(loop=self.loop)
  40. @asyncio.coroutine
  41. def acquire_lock():
  42. return (yield from lock)
  43. res = self.loop.run_until_complete(acquire_lock())
  44. self.assertTrue(res)
  45. self.assertTrue(lock.locked())
  46. lock.release()
  47. self.assertFalse(lock.locked())
  48. def test_acquire(self):
  49. lock = asyncio.Lock(loop=self.loop)
  50. result = []
  51. self.assertTrue(self.loop.run_until_complete(lock.acquire()))
  52. @asyncio.coroutine
  53. def c1(result):
  54. if (yield from lock.acquire()):
  55. result.append(1)
  56. return True
  57. @asyncio.coroutine
  58. def c2(result):
  59. if (yield from lock.acquire()):
  60. result.append(2)
  61. return True
  62. @asyncio.coroutine
  63. def c3(result):
  64. if (yield from lock.acquire()):
  65. result.append(3)
  66. return True
  67. t1 = asyncio.Task(c1(result), loop=self.loop)
  68. t2 = asyncio.Task(c2(result), loop=self.loop)
  69. test_utils.run_briefly(self.loop)
  70. self.assertEqual([], result)
  71. lock.release()
  72. test_utils.run_briefly(self.loop)
  73. self.assertEqual([1], result)
  74. test_utils.run_briefly(self.loop)
  75. self.assertEqual([1], result)
  76. t3 = asyncio.Task(c3(result), loop=self.loop)
  77. lock.release()
  78. test_utils.run_briefly(self.loop)
  79. self.assertEqual([1, 2], result)
  80. lock.release()
  81. test_utils.run_briefly(self.loop)
  82. self.assertEqual([1, 2, 3], result)
  83. self.assertTrue(t1.done())
  84. self.assertTrue(t1.result())
  85. self.assertTrue(t2.done())
  86. self.assertTrue(t2.result())
  87. self.assertTrue(t3.done())
  88. self.assertTrue(t3.result())
  89. def test_acquire_cancel(self):
  90. lock = asyncio.Lock(loop=self.loop)
  91. self.assertTrue(self.loop.run_until_complete(lock.acquire()))
  92. task = asyncio.Task(lock.acquire(), loop=self.loop)
  93. self.loop.call_soon(task.cancel)
  94. self.assertRaises(
  95. asyncio.CancelledError,
  96. self.loop.run_until_complete, task)
  97. self.assertFalse(lock._waiters)
  98. def test_cancel_race(self):
  99. # Several tasks:
  100. # - A acquires the lock
  101. # - B is blocked in acquire()
  102. # - C is blocked in acquire()
  103. #
  104. # Now, concurrently:
  105. # - B is cancelled
  106. # - A releases the lock
  107. #
  108. # If B's waiter is marked cancelled but not yet removed from
  109. # _waiters, A's release() call will crash when trying to set
  110. # B's waiter; instead, it should move on to C's waiter.
  111. # Setup: A has the lock, b and c are waiting.
  112. lock = asyncio.Lock(loop=self.loop)
  113. @asyncio.coroutine
  114. def lockit(name, blocker):
  115. yield from lock.acquire()
  116. try:
  117. if blocker is not None:
  118. yield from blocker
  119. finally:
  120. lock.release()
  121. fa = asyncio.Future(loop=self.loop)
  122. ta = asyncio.Task(lockit('A', fa), loop=self.loop)
  123. test_utils.run_briefly(self.loop)
  124. self.assertTrue(lock.locked())
  125. tb = asyncio.Task(lockit('B', None), loop=self.loop)
  126. test_utils.run_briefly(self.loop)
  127. self.assertEqual(len(lock._waiters), 1)
  128. tc = asyncio.Task(lockit('C', None), loop=self.loop)
  129. test_utils.run_briefly(self.loop)
  130. self.assertEqual(len(lock._waiters), 2)
  131. # Create the race and check.
  132. # Without the fix this failed at the last assert.
  133. fa.set_result(None)
  134. tb.cancel()
  135. self.assertTrue(lock._waiters[0].cancelled())
  136. test_utils.run_briefly(self.loop)
  137. self.assertFalse(lock.locked())
  138. self.assertTrue(ta.done())
  139. self.assertTrue(tb.cancelled())
  140. self.assertTrue(tc.done())
  141. def test_release_not_acquired(self):
  142. lock = asyncio.Lock(loop=self.loop)
  143. self.assertRaises(RuntimeError, lock.release)
  144. def test_release_no_waiters(self):
  145. lock = asyncio.Lock(loop=self.loop)
  146. self.loop.run_until_complete(lock.acquire())
  147. self.assertTrue(lock.locked())
  148. lock.release()
  149. self.assertFalse(lock.locked())
  150. def test_context_manager(self):
  151. lock = asyncio.Lock(loop=self.loop)
  152. @asyncio.coroutine
  153. def acquire_lock():
  154. return (yield from lock)
  155. with self.loop.run_until_complete(acquire_lock()):
  156. self.assertTrue(lock.locked())
  157. self.assertFalse(lock.locked())
  158. def test_context_manager_cant_reuse(self):
  159. lock = asyncio.Lock(loop=self.loop)
  160. @asyncio.coroutine
  161. def acquire_lock():
  162. return (yield from lock)
  163. # This spells "yield from lock" outside a generator.
  164. cm = self.loop.run_until_complete(acquire_lock())
  165. with cm:
  166. self.assertTrue(lock.locked())
  167. self.assertFalse(lock.locked())
  168. with self.assertRaises(AttributeError):
  169. with cm:
  170. pass
  171. def test_context_manager_no_yield(self):
  172. lock = asyncio.Lock(loop=self.loop)
  173. try:
  174. with lock:
  175. self.fail('RuntimeError is not raised in with expression')
  176. except RuntimeError as err:
  177. self.assertEqual(
  178. str(err),
  179. '"yield from" should be used as context manager expression')
  180. self.assertFalse(lock.locked())
  181. class EventTests(test_utils.TestCase):
  182. def setUp(self):
  183. super().setUp()
  184. self.loop = self.new_test_loop()
  185. def test_ctor_loop(self):
  186. loop = mock.Mock()
  187. ev = asyncio.Event(loop=loop)
  188. self.assertIs(ev._loop, loop)
  189. ev = asyncio.Event(loop=self.loop)
  190. self.assertIs(ev._loop, self.loop)
  191. def test_ctor_noloop(self):
  192. asyncio.set_event_loop(self.loop)
  193. ev = asyncio.Event()
  194. self.assertIs(ev._loop, self.loop)
  195. def test_repr(self):
  196. ev = asyncio.Event(loop=self.loop)
  197. self.assertTrue(repr(ev).endswith('[unset]>'))
  198. match = RGX_REPR.match(repr(ev))
  199. self.assertEqual(match.group('extras'), 'unset')
  200. ev.set()
  201. self.assertTrue(repr(ev).endswith('[set]>'))
  202. self.assertTrue(RGX_REPR.match(repr(ev)))
  203. ev._waiters.append(mock.Mock())
  204. self.assertTrue('waiters:1' in repr(ev))
  205. self.assertTrue(RGX_REPR.match(repr(ev)))
  206. def test_wait(self):
  207. ev = asyncio.Event(loop=self.loop)
  208. self.assertFalse(ev.is_set())
  209. result = []
  210. @asyncio.coroutine
  211. def c1(result):
  212. if (yield from ev.wait()):
  213. result.append(1)
  214. @asyncio.coroutine
  215. def c2(result):
  216. if (yield from ev.wait()):
  217. result.append(2)
  218. @asyncio.coroutine
  219. def c3(result):
  220. if (yield from ev.wait()):
  221. result.append(3)
  222. t1 = asyncio.Task(c1(result), loop=self.loop)
  223. t2 = asyncio.Task(c2(result), loop=self.loop)
  224. test_utils.run_briefly(self.loop)
  225. self.assertEqual([], result)
  226. t3 = asyncio.Task(c3(result), loop=self.loop)
  227. ev.set()
  228. test_utils.run_briefly(self.loop)
  229. self.assertEqual([3, 1, 2], result)
  230. self.assertTrue(t1.done())
  231. self.assertIsNone(t1.result())
  232. self.assertTrue(t2.done())
  233. self.assertIsNone(t2.result())
  234. self.assertTrue(t3.done())
  235. self.assertIsNone(t3.result())
  236. def test_wait_on_set(self):
  237. ev = asyncio.Event(loop=self.loop)
  238. ev.set()
  239. res = self.loop.run_until_complete(ev.wait())
  240. self.assertTrue(res)
  241. def test_wait_cancel(self):
  242. ev = asyncio.Event(loop=self.loop)
  243. wait = asyncio.Task(ev.wait(), loop=self.loop)
  244. self.loop.call_soon(wait.cancel)
  245. self.assertRaises(
  246. asyncio.CancelledError,
  247. self.loop.run_until_complete, wait)
  248. self.assertFalse(ev._waiters)
  249. def test_clear(self):
  250. ev = asyncio.Event(loop=self.loop)
  251. self.assertFalse(ev.is_set())
  252. ev.set()
  253. self.assertTrue(ev.is_set())
  254. ev.clear()
  255. self.assertFalse(ev.is_set())
  256. def test_clear_with_waiters(self):
  257. ev = asyncio.Event(loop=self.loop)
  258. result = []
  259. @asyncio.coroutine
  260. def c1(result):
  261. if (yield from ev.wait()):
  262. result.append(1)
  263. return True
  264. t = asyncio.Task(c1(result), loop=self.loop)
  265. test_utils.run_briefly(self.loop)
  266. self.assertEqual([], result)
  267. ev.set()
  268. ev.clear()
  269. self.assertFalse(ev.is_set())
  270. ev.set()
  271. ev.set()
  272. self.assertEqual(1, len(ev._waiters))
  273. test_utils.run_briefly(self.loop)
  274. self.assertEqual([1], result)
  275. self.assertEqual(0, len(ev._waiters))
  276. self.assertTrue(t.done())
  277. self.assertTrue(t.result())
  278. class ConditionTests(test_utils.TestCase):
  279. def setUp(self):
  280. super().setUp()
  281. self.loop = self.new_test_loop()
  282. def test_ctor_loop(self):
  283. loop = mock.Mock()
  284. cond = asyncio.Condition(loop=loop)
  285. self.assertIs(cond._loop, loop)
  286. cond = asyncio.Condition(loop=self.loop)
  287. self.assertIs(cond._loop, self.loop)
  288. def test_ctor_noloop(self):
  289. asyncio.set_event_loop(self.loop)
  290. cond = asyncio.Condition()
  291. self.assertIs(cond._loop, self.loop)
  292. def test_wait(self):
  293. cond = asyncio.Condition(loop=self.loop)
  294. result = []
  295. @asyncio.coroutine
  296. def c1(result):
  297. yield from cond.acquire()
  298. if (yield from cond.wait()):
  299. result.append(1)
  300. return True
  301. @asyncio.coroutine
  302. def c2(result):
  303. yield from cond.acquire()
  304. if (yield from cond.wait()):
  305. result.append(2)
  306. return True
  307. @asyncio.coroutine
  308. def c3(result):
  309. yield from cond.acquire()
  310. if (yield from cond.wait()):
  311. result.append(3)
  312. return True
  313. t1 = asyncio.Task(c1(result), loop=self.loop)
  314. t2 = asyncio.Task(c2(result), loop=self.loop)
  315. t3 = asyncio.Task(c3(result), loop=self.loop)
  316. test_utils.run_briefly(self.loop)
  317. self.assertEqual([], result)
  318. self.assertFalse(cond.locked())
  319. self.assertTrue(self.loop.run_until_complete(cond.acquire()))
  320. cond.notify()
  321. test_utils.run_briefly(self.loop)
  322. self.assertEqual([], result)
  323. self.assertTrue(cond.locked())
  324. cond.release()
  325. test_utils.run_briefly(self.loop)
  326. self.assertEqual([1], result)
  327. self.assertTrue(cond.locked())
  328. cond.notify(2)
  329. test_utils.run_briefly(self.loop)
  330. self.assertEqual([1], result)
  331. self.assertTrue(cond.locked())
  332. cond.release()
  333. test_utils.run_briefly(self.loop)
  334. self.assertEqual([1, 2], result)
  335. self.assertTrue(cond.locked())
  336. cond.release()
  337. test_utils.run_briefly(self.loop)
  338. self.assertEqual([1, 2, 3], result)
  339. self.assertTrue(cond.locked())
  340. self.assertTrue(t1.done())
  341. self.assertTrue(t1.result())
  342. self.assertTrue(t2.done())
  343. self.assertTrue(t2.result())
  344. self.assertTrue(t3.done())
  345. self.assertTrue(t3.result())
  346. def test_wait_cancel(self):
  347. cond = asyncio.Condition(loop=self.loop)
  348. self.loop.run_until_complete(cond.acquire())
  349. wait = asyncio.Task(cond.wait(), loop=self.loop)
  350. self.loop.call_soon(wait.cancel)
  351. self.assertRaises(
  352. asyncio.CancelledError,
  353. self.loop.run_until_complete, wait)
  354. self.assertFalse(cond._waiters)
  355. self.assertTrue(cond.locked())
  356. def test_wait_cancel_contested(self):
  357. cond = asyncio.Condition(loop=self.loop)
  358. self.loop.run_until_complete(cond.acquire())
  359. self.assertTrue(cond.locked())
  360. wait_task = asyncio.Task(cond.wait(), loop=self.loop)
  361. test_utils.run_briefly(self.loop)
  362. self.assertFalse(cond.locked())
  363. # Notify, but contest the lock before cancelling
  364. self.loop.run_until_complete(cond.acquire())
  365. self.assertTrue(cond.locked())
  366. cond.notify()
  367. self.loop.call_soon(wait_task.cancel)
  368. self.loop.call_soon(cond.release)
  369. try:
  370. self.loop.run_until_complete(wait_task)
  371. except asyncio.CancelledError:
  372. # Should not happen, since no cancellation points
  373. pass
  374. self.assertTrue(cond.locked())
  375. def test_wait_unacquired(self):
  376. cond = asyncio.Condition(loop=self.loop)
  377. self.assertRaises(
  378. RuntimeError,
  379. self.loop.run_until_complete, cond.wait())
  380. def test_wait_for(self):
  381. cond = asyncio.Condition(loop=self.loop)
  382. presult = False
  383. def predicate():
  384. return presult
  385. result = []
  386. @asyncio.coroutine
  387. def c1(result):
  388. yield from cond.acquire()
  389. if (yield from cond.wait_for(predicate)):
  390. result.append(1)
  391. cond.release()
  392. return True
  393. t = asyncio.Task(c1(result), loop=self.loop)
  394. test_utils.run_briefly(self.loop)
  395. self.assertEqual([], result)
  396. self.loop.run_until_complete(cond.acquire())
  397. cond.notify()
  398. cond.release()
  399. test_utils.run_briefly(self.loop)
  400. self.assertEqual([], result)
  401. presult = True
  402. self.loop.run_until_complete(cond.acquire())
  403. cond.notify()
  404. cond.release()
  405. test_utils.run_briefly(self.loop)
  406. self.assertEqual([1], result)
  407. self.assertTrue(t.done())
  408. self.assertTrue(t.result())
  409. def test_wait_for_unacquired(self):
  410. cond = asyncio.Condition(loop=self.loop)
  411. # predicate can return true immediately
  412. res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3]))
  413. self.assertEqual([1, 2, 3], res)
  414. self.assertRaises(
  415. RuntimeError,
  416. self.loop.run_until_complete,
  417. cond.wait_for(lambda: False))
  418. def test_notify(self):
  419. cond = asyncio.Condition(loop=self.loop)
  420. result = []
  421. @asyncio.coroutine
  422. def c1(result):
  423. yield from cond.acquire()
  424. if (yield from cond.wait()):
  425. result.append(1)
  426. cond.release()
  427. return True
  428. @asyncio.coroutine
  429. def c2(result):
  430. yield from cond.acquire()
  431. if (yield from cond.wait()):
  432. result.append(2)
  433. cond.release()
  434. return True
  435. @asyncio.coroutine
  436. def c3(result):
  437. yield from cond.acquire()
  438. if (yield from cond.wait()):
  439. result.append(3)
  440. cond.release()
  441. return True
  442. t1 = asyncio.Task(c1(result), loop=self.loop)
  443. t2 = asyncio.Task(c2(result), loop=self.loop)
  444. t3 = asyncio.Task(c3(result), loop=self.loop)
  445. test_utils.run_briefly(self.loop)
  446. self.assertEqual([], result)
  447. self.loop.run_until_complete(cond.acquire())
  448. cond.notify(1)
  449. cond.release()
  450. test_utils.run_briefly(self.loop)
  451. self.assertEqual([1], result)
  452. self.loop.run_until_complete(cond.acquire())
  453. cond.notify(1)
  454. cond.notify(2048)
  455. cond.release()
  456. test_utils.run_briefly(self.loop)
  457. self.assertEqual([1, 2, 3], result)
  458. self.assertTrue(t1.done())
  459. self.assertTrue(t1.result())
  460. self.assertTrue(t2.done())
  461. self.assertTrue(t2.result())
  462. self.assertTrue(t3.done())
  463. self.assertTrue(t3.result())
  464. def test_notify_all(self):
  465. cond = asyncio.Condition(loop=self.loop)
  466. result = []
  467. @asyncio.coroutine
  468. def c1(result):
  469. yield from cond.acquire()
  470. if (yield from cond.wait()):
  471. result.append(1)
  472. cond.release()
  473. return True
  474. @asyncio.coroutine
  475. def c2(result):
  476. yield from cond.acquire()
  477. if (yield from cond.wait()):
  478. result.append(2)
  479. cond.release()
  480. return True
  481. t1 = asyncio.Task(c1(result), loop=self.loop)
  482. t2 = asyncio.Task(c2(result), loop=self.loop)
  483. test_utils.run_briefly(self.loop)
  484. self.assertEqual([], result)
  485. self.loop.run_until_complete(cond.acquire())
  486. cond.notify_all()
  487. cond.release()
  488. test_utils.run_briefly(self.loop)
  489. self.assertEqual([1, 2], result)
  490. self.assertTrue(t1.done())
  491. self.assertTrue(t1.result())
  492. self.assertTrue(t2.done())
  493. self.assertTrue(t2.result())
  494. def test_notify_unacquired(self):
  495. cond = asyncio.Condition(loop=self.loop)
  496. self.assertRaises(RuntimeError, cond.notify)
  497. def test_notify_all_unacquired(self):
  498. cond = asyncio.Condition(loop=self.loop)
  499. self.assertRaises(RuntimeError, cond.notify_all)
  500. def test_repr(self):
  501. cond = asyncio.Condition(loop=self.loop)
  502. self.assertTrue('unlocked' in repr(cond))
  503. self.assertTrue(RGX_REPR.match(repr(cond)))
  504. self.loop.run_until_complete(cond.acquire())
  505. self.assertTrue('locked' in repr(cond))
  506. cond._waiters.append(mock.Mock())
  507. self.assertTrue('waiters:1' in repr(cond))
  508. self.assertTrue(RGX_REPR.match(repr(cond)))
  509. cond._waiters.append(mock.Mock())
  510. self.assertTrue('waiters:2' in repr(cond))
  511. self.assertTrue(RGX_REPR.match(repr(cond)))
  512. def test_context_manager(self):
  513. cond = asyncio.Condition(loop=self.loop)
  514. @asyncio.coroutine
  515. def acquire_cond():
  516. return (yield from cond)
  517. with self.loop.run_until_complete(acquire_cond()):
  518. self.assertTrue(cond.locked())
  519. self.assertFalse(cond.locked())
  520. def test_context_manager_no_yield(self):
  521. cond = asyncio.Condition(loop=self.loop)
  522. try:
  523. with cond:
  524. self.fail('RuntimeError is not raised in with expression')
  525. except RuntimeError as err:
  526. self.assertEqual(
  527. str(err),
  528. '"yield from" should be used as context manager expression')
  529. self.assertFalse(cond.locked())
  530. def test_explicit_lock(self):
  531. lock = asyncio.Lock(loop=self.loop)
  532. cond = asyncio.Condition(lock, loop=self.loop)
  533. self.assertIs(cond._lock, lock)
  534. self.assertIs(cond._loop, lock._loop)
  535. def test_ambiguous_loops(self):
  536. loop = self.new_test_loop()
  537. self.addCleanup(loop.close)
  538. lock = asyncio.Lock(loop=self.loop)
  539. with self.assertRaises(ValueError):
  540. asyncio.Condition(lock, loop=loop)
  541. class SemaphoreTests(test_utils.TestCase):
  542. def setUp(self):
  543. super().setUp()
  544. self.loop = self.new_test_loop()
  545. def test_ctor_loop(self):
  546. loop = mock.Mock()
  547. sem = asyncio.Semaphore(loop=loop)
  548. self.assertIs(sem._loop, loop)
  549. sem = asyncio.Semaphore(loop=self.loop)
  550. self.assertIs(sem._loop, self.loop)
  551. def test_ctor_noloop(self):
  552. asyncio.set_event_loop(self.loop)
  553. sem = asyncio.Semaphore()
  554. self.assertIs(sem._loop, self.loop)
  555. def test_initial_value_zero(self):
  556. sem = asyncio.Semaphore(0, loop=self.loop)
  557. self.assertTrue(sem.locked())
  558. def test_repr(self):
  559. sem = asyncio.Semaphore(loop=self.loop)
  560. self.assertTrue(repr(sem).endswith('[unlocked,value:1]>'))
  561. self.assertTrue(RGX_REPR.match(repr(sem)))
  562. self.loop.run_until_complete(sem.acquire())
  563. self.assertTrue(repr(sem).endswith('[locked]>'))
  564. self.assertTrue('waiters' not in repr(sem))
  565. self.assertTrue(RGX_REPR.match(repr(sem)))
  566. sem._waiters.append(mock.Mock())
  567. self.assertTrue('waiters:1' in repr(sem))
  568. self.assertTrue(RGX_REPR.match(repr(sem)))
  569. sem._waiters.append(mock.Mock())
  570. self.assertTrue('waiters:2' in repr(sem))
  571. self.assertTrue(RGX_REPR.match(repr(sem)))
  572. def test_semaphore(self):
  573. sem = asyncio.Semaphore(loop=self.loop)
  574. self.assertEqual(1, sem._value)
  575. @asyncio.coroutine
  576. def acquire_lock():
  577. return (yield from sem)
  578. res = self.loop.run_until_complete(acquire_lock())
  579. self.assertTrue(res)
  580. self.assertTrue(sem.locked())
  581. self.assertEqual(0, sem._value)
  582. sem.release()
  583. self.assertFalse(sem.locked())
  584. self.assertEqual(1, sem._value)
  585. def test_semaphore_value(self):
  586. self.assertRaises(ValueError, asyncio.Semaphore, -1)
  587. def test_acquire(self):
  588. sem = asyncio.Semaphore(3, loop=self.loop)
  589. result = []
  590. self.assertTrue(self.loop.run_until_complete(sem.acquire()))
  591. self.assertTrue(self.loop.run_until_complete(sem.acquire()))
  592. self.assertFalse(sem.locked())
  593. @asyncio.coroutine
  594. def c1(result):
  595. yield from sem.acquire()
  596. result.append(1)
  597. return True
  598. @asyncio.coroutine
  599. def c2(result):
  600. yield from sem.acquire()
  601. result.append(2)
  602. return True
  603. @asyncio.coroutine
  604. def c3(result):
  605. yield from sem.acquire()
  606. result.append(3)
  607. return True
  608. @asyncio.coroutine
  609. def c4(result):
  610. yield from sem.acquire()
  611. result.append(4)
  612. return True
  613. t1 = asyncio.Task(c1(result), loop=self.loop)
  614. t2 = asyncio.Task(c2(result), loop=self.loop)
  615. t3 = asyncio.Task(c3(result), loop=self.loop)
  616. test_utils.run_briefly(self.loop)
  617. self.assertEqual([1], result)
  618. self.assertTrue(sem.locked())
  619. self.assertEqual(2, len(sem._waiters))
  620. self.assertEqual(0, sem._value)
  621. t4 = asyncio.Task(c4(result), loop=self.loop)
  622. sem.release()
  623. sem.release()
  624. self.assertEqual(2, sem._value)
  625. test_utils.run_briefly(self.loop)
  626. self.assertEqual(0, sem._value)
  627. self.assertEqual(3, len(result))
  628. self.assertTrue(sem.locked())
  629. self.assertEqual(1, len(sem._waiters))
  630. self.assertEqual(0, sem._value)
  631. self.assertTrue(t1.done())
  632. self.assertTrue(t1.result())
  633. race_tasks = [t2, t3, t4]
  634. done_tasks = [t for t in race_tasks if t.done() and t.result()]
  635. self.assertTrue(2, len(done_tasks))
  636. # cleanup locked semaphore
  637. sem.release()
  638. self.loop.run_until_complete(asyncio.gather(*race_tasks))
  639. def test_acquire_cancel(self):
  640. sem = asyncio.Semaphore(loop=self.loop)
  641. self.loop.run_until_complete(sem.acquire())
  642. acquire = asyncio.Task(sem.acquire(), loop=self.loop)
  643. self.loop.call_soon(acquire.cancel)
  644. self.assertRaises(
  645. asyncio.CancelledError,
  646. self.loop.run_until_complete, acquire)
  647. self.assertTrue((not sem._waiters) or
  648. all(waiter.done() for waiter in sem._waiters))
  649. def test_acquire_cancel_before_awoken(self):
  650. sem = asyncio.Semaphore(value=0, loop=self.loop)
  651. t1 = asyncio.Task(sem.acquire(), loop=self.loop)
  652. t2 = asyncio.Task(sem.acquire(), loop=self.loop)
  653. t3 = asyncio.Task(sem.acquire(), loop=self.loop)
  654. t4 = asyncio.Task(sem.acquire(), loop=self.loop)
  655. test_utils.run_briefly(self.loop)
  656. sem.release()
  657. t1.cancel()
  658. t2.cancel()
  659. test_utils.run_briefly(self.loop)
  660. num_done = sum(t.done() for t in [t3, t4])
  661. self.assertEqual(num_done, 1)
  662. t3.cancel()
  663. t4.cancel()
  664. test_utils.run_briefly(self.loop)
  665. def test_acquire_hang(self):
  666. sem = asyncio.Semaphore(value=0, loop=self.loop)
  667. t1 = asyncio.Task(sem.acquire(), loop=self.loop)
  668. t2 = asyncio.Task(sem.acquire(), loop=self.loop)
  669. test_utils.run_briefly(self.loop)
  670. sem.release()
  671. t1.cancel()
  672. test_utils.run_briefly(self.loop)
  673. self.assertTrue(sem.locked())
  674. def test_release_not_acquired(self):
  675. sem = asyncio.BoundedSemaphore(loop=self.loop)
  676. self.assertRaises(ValueError, sem.release)
  677. def test_release_no_waiters(self):
  678. sem = asyncio.Semaphore(loop=self.loop)
  679. self.loop.run_until_complete(sem.acquire())
  680. self.assertTrue(sem.locked())
  681. sem.release()
  682. self.assertFalse(sem.locked())
  683. def test_context_manager(self):
  684. sem = asyncio.Semaphore(2, loop=self.loop)
  685. @asyncio.coroutine
  686. def acquire_lock():
  687. return (yield from sem)
  688. with self.loop.run_until_complete(acquire_lock()):
  689. self.assertFalse(sem.locked())
  690. self.assertEqual(1, sem._value)
  691. with self.loop.run_until_complete(acquire_lock()):
  692. self.assertTrue(sem.locked())
  693. self.assertEqual(2, sem._value)
  694. def test_context_manager_no_yield(self):
  695. sem = asyncio.Semaphore(2, loop=self.loop)
  696. try:
  697. with sem:
  698. self.fail('RuntimeError is not raised in with expression')
  699. except RuntimeError as err:
  700. self.assertEqual(
  701. str(err),
  702. '"yield from" should be used as context manager expression')
  703. self.assertEqual(2, sem._value)
  704. if __name__ == '__main__':
  705. unittest.main()