test_futures.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. import os
  2. import subprocess
  3. import sys
  4. import threading
  5. import functools
  6. import contextlib
  7. import logging
  8. import re
  9. import time
  10. from StringIO import StringIO
  11. from test import test_support
  12. from concurrent import futures
  13. from concurrent.futures._base import (
  14. PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future)
  15. try:
  16. import unittest2 as unittest
  17. except ImportError:
  18. import unittest
  19. def reap_threads(func):
  20. """Use this function when threads are being used. This will
  21. ensure that the threads are cleaned up even when the test fails.
  22. If threading is unavailable this function does nothing.
  23. """
  24. @functools.wraps(func)
  25. def decorator(*args):
  26. key = test_support.threading_setup()
  27. try:
  28. return func(*args)
  29. finally:
  30. test_support.threading_cleanup(*key)
  31. return decorator
  32. # Executing the interpreter in a subprocess
  33. def _assert_python(expected_success, *args, **env_vars):
  34. cmd_line = [sys.executable]
  35. if not env_vars:
  36. cmd_line.append('-E')
  37. # Need to preserve the original environment, for in-place testing of
  38. # shared library builds.
  39. env = os.environ.copy()
  40. # But a special flag that can be set to override -- in this case, the
  41. # caller is responsible to pass the full environment.
  42. if env_vars.pop('__cleanenv', None):
  43. env = {}
  44. env.update(env_vars)
  45. cmd_line.extend(args)
  46. p = subprocess.Popen(cmd_line, stdin=subprocess.PIPE,
  47. stdout=subprocess.PIPE, stderr=subprocess.PIPE,
  48. env=env)
  49. try:
  50. out, err = p.communicate()
  51. finally:
  52. subprocess._cleanup()
  53. p.stdout.close()
  54. p.stderr.close()
  55. rc = p.returncode
  56. err = strip_python_stderr(err)
  57. if (rc and expected_success) or (not rc and not expected_success):
  58. raise AssertionError(
  59. "Process return code is %d, "
  60. "stderr follows:\n%s" % (rc, err.decode('ascii', 'ignore')))
  61. return rc, out, err
  62. def assert_python_ok(*args, **env_vars):
  63. """
  64. Assert that running the interpreter with `args` and optional environment
  65. variables `env_vars` is ok and return a (return code, stdout, stderr) tuple.
  66. """
  67. return _assert_python(True, *args, **env_vars)
  68. def strip_python_stderr(stderr):
  69. """Strip the stderr of a Python process from potential debug output
  70. emitted by the interpreter.
  71. This will typically be run on the result of the communicate() method
  72. of a subprocess.Popen object.
  73. """
  74. stderr = re.sub(r"\[\d+ refs\]\r?\n?$".encode(), "".encode(), stderr).strip()
  75. return stderr
  76. @contextlib.contextmanager
  77. def captured_stderr():
  78. """Return a context manager used by captured_stdout/stdin/stderr
  79. that temporarily replaces the sys stream *stream_name* with a StringIO."""
  80. logging_stream = StringIO()
  81. handler = logging.StreamHandler(logging_stream)
  82. logging.root.addHandler(handler)
  83. try:
  84. yield logging_stream
  85. finally:
  86. logging.root.removeHandler(handler)
  87. def create_future(state=PENDING, exception=None, result=None):
  88. f = Future()
  89. f._state = state
  90. f._exception = exception
  91. f._result = result
  92. return f
  93. PENDING_FUTURE = create_future(state=PENDING)
  94. RUNNING_FUTURE = create_future(state=RUNNING)
  95. CANCELLED_FUTURE = create_future(state=CANCELLED)
  96. CANCELLED_AND_NOTIFIED_FUTURE = create_future(state=CANCELLED_AND_NOTIFIED)
  97. EXCEPTION_FUTURE = create_future(state=FINISHED, exception=IOError())
  98. SUCCESSFUL_FUTURE = create_future(state=FINISHED, result=42)
  99. def mul(x, y):
  100. return x * y
  101. def sleep_and_raise(t):
  102. time.sleep(t)
  103. raise Exception('this is an exception')
  104. def sleep_and_print(t, msg):
  105. time.sleep(t)
  106. print(msg)
  107. sys.stdout.flush()
  108. class ExecutorMixin:
  109. worker_count = 5
  110. def setUp(self):
  111. self.t1 = time.time()
  112. try:
  113. self.executor = self.executor_type(max_workers=self.worker_count)
  114. except NotImplementedError:
  115. e = sys.exc_info()[1]
  116. self.skipTest(str(e))
  117. self._prime_executor()
  118. def tearDown(self):
  119. self.executor.shutdown(wait=True)
  120. dt = time.time() - self.t1
  121. if test_support.verbose:
  122. print("%.2fs" % dt)
  123. self.assertLess(dt, 60, "synchronization issue: test lasted too long")
  124. def _prime_executor(self):
  125. # Make sure that the executor is ready to do work before running the
  126. # tests. This should reduce the probability of timeouts in the tests.
  127. futures = [self.executor.submit(time.sleep, 0.1)
  128. for _ in range(self.worker_count)]
  129. for f in futures:
  130. f.result()
  131. class ThreadPoolMixin(ExecutorMixin):
  132. executor_type = futures.ThreadPoolExecutor
  133. class ProcessPoolMixin(ExecutorMixin):
  134. executor_type = futures.ProcessPoolExecutor
  135. class ExecutorShutdownTest(unittest.TestCase):
  136. def test_run_after_shutdown(self):
  137. self.executor.shutdown()
  138. self.assertRaises(RuntimeError,
  139. self.executor.submit,
  140. pow, 2, 5)
  141. def test_interpreter_shutdown(self):
  142. # Test the atexit hook for shutdown of worker threads and processes
  143. rc, out, err = assert_python_ok('-c', """if 1:
  144. from concurrent.futures import %s
  145. from time import sleep
  146. from test_futures import sleep_and_print
  147. t = %s(5)
  148. t.submit(sleep_and_print, 1.0, "apple")
  149. """ % (self.executor_type.__name__, self.executor_type.__name__))
  150. # Errors in atexit hooks don't change the process exit code, check
  151. # stderr manually.
  152. self.assertFalse(err)
  153. self.assertEqual(out.strip(), "apple".encode())
  154. def test_hang_issue12364(self):
  155. fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)]
  156. self.executor.shutdown()
  157. for f in fs:
  158. f.result()
  159. class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest):
  160. def _prime_executor(self):
  161. pass
  162. def test_threads_terminate(self):
  163. self.executor.submit(mul, 21, 2)
  164. self.executor.submit(mul, 6, 7)
  165. self.executor.submit(mul, 3, 14)
  166. self.assertEqual(len(self.executor._threads), 3)
  167. self.executor.shutdown()
  168. for t in self.executor._threads:
  169. t.join()
  170. def test_context_manager_shutdown(self):
  171. with futures.ThreadPoolExecutor(max_workers=5) as e:
  172. executor = e
  173. self.assertEqual(list(e.map(abs, range(-5, 5))),
  174. [5, 4, 3, 2, 1, 0, 1, 2, 3, 4])
  175. for t in executor._threads:
  176. t.join()
  177. def test_del_shutdown(self):
  178. executor = futures.ThreadPoolExecutor(max_workers=5)
  179. executor.map(abs, range(-5, 5))
  180. threads = executor._threads
  181. del executor
  182. for t in threads:
  183. t.join()
  184. class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
  185. def _prime_executor(self):
  186. pass
  187. def test_processes_terminate(self):
  188. self.executor.submit(mul, 21, 2)
  189. self.executor.submit(mul, 6, 7)
  190. self.executor.submit(mul, 3, 14)
  191. self.assertEqual(len(self.executor._processes), 5)
  192. processes = self.executor._processes
  193. self.executor.shutdown()
  194. for p in processes:
  195. p.join()
  196. def test_context_manager_shutdown(self):
  197. with futures.ProcessPoolExecutor(max_workers=5) as e:
  198. processes = e._processes
  199. self.assertEqual(list(e.map(abs, range(-5, 5))),
  200. [5, 4, 3, 2, 1, 0, 1, 2, 3, 4])
  201. for p in processes:
  202. p.join()
  203. def test_del_shutdown(self):
  204. executor = futures.ProcessPoolExecutor(max_workers=5)
  205. list(executor.map(abs, range(-5, 5)))
  206. queue_management_thread = executor._queue_management_thread
  207. processes = executor._processes
  208. del executor
  209. queue_management_thread.join()
  210. for p in processes:
  211. p.join()
  212. class WaitTests(unittest.TestCase):
  213. def test_first_completed(self):
  214. future1 = self.executor.submit(mul, 21, 2)
  215. future2 = self.executor.submit(time.sleep, 1.5)
  216. done, not_done = futures.wait(
  217. [CANCELLED_FUTURE, future1, future2],
  218. return_when=futures.FIRST_COMPLETED)
  219. self.assertEqual(set([future1]), done)
  220. self.assertEqual(set([CANCELLED_FUTURE, future2]), not_done)
  221. def test_first_completed_some_already_completed(self):
  222. future1 = self.executor.submit(time.sleep, 1.5)
  223. finished, pending = futures.wait(
  224. [CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE, future1],
  225. return_when=futures.FIRST_COMPLETED)
  226. self.assertEqual(
  227. set([CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE]),
  228. finished)
  229. self.assertEqual(set([future1]), pending)
  230. def test_first_exception(self):
  231. future1 = self.executor.submit(mul, 2, 21)
  232. future2 = self.executor.submit(sleep_and_raise, 1.5)
  233. future3 = self.executor.submit(time.sleep, 3)
  234. finished, pending = futures.wait(
  235. [future1, future2, future3],
  236. return_when=futures.FIRST_EXCEPTION)
  237. self.assertEqual(set([future1, future2]), finished)
  238. self.assertEqual(set([future3]), pending)
  239. def test_first_exception_some_already_complete(self):
  240. future1 = self.executor.submit(divmod, 21, 0)
  241. future2 = self.executor.submit(time.sleep, 1.5)
  242. finished, pending = futures.wait(
  243. [SUCCESSFUL_FUTURE,
  244. CANCELLED_FUTURE,
  245. CANCELLED_AND_NOTIFIED_FUTURE,
  246. future1, future2],
  247. return_when=futures.FIRST_EXCEPTION)
  248. self.assertEqual(set([SUCCESSFUL_FUTURE,
  249. CANCELLED_AND_NOTIFIED_FUTURE,
  250. future1]), finished)
  251. self.assertEqual(set([CANCELLED_FUTURE, future2]), pending)
  252. def test_first_exception_one_already_failed(self):
  253. future1 = self.executor.submit(time.sleep, 2)
  254. finished, pending = futures.wait(
  255. [EXCEPTION_FUTURE, future1],
  256. return_when=futures.FIRST_EXCEPTION)
  257. self.assertEqual(set([EXCEPTION_FUTURE]), finished)
  258. self.assertEqual(set([future1]), pending)
  259. def test_all_completed(self):
  260. future1 = self.executor.submit(divmod, 2, 0)
  261. future2 = self.executor.submit(mul, 2, 21)
  262. finished, pending = futures.wait(
  263. [SUCCESSFUL_FUTURE,
  264. CANCELLED_AND_NOTIFIED_FUTURE,
  265. EXCEPTION_FUTURE,
  266. future1,
  267. future2],
  268. return_when=futures.ALL_COMPLETED)
  269. self.assertEqual(set([SUCCESSFUL_FUTURE,
  270. CANCELLED_AND_NOTIFIED_FUTURE,
  271. EXCEPTION_FUTURE,
  272. future1,
  273. future2]), finished)
  274. self.assertEqual(set(), pending)
  275. def test_timeout(self):
  276. future1 = self.executor.submit(mul, 6, 7)
  277. future2 = self.executor.submit(time.sleep, 3)
  278. finished, pending = futures.wait(
  279. [CANCELLED_AND_NOTIFIED_FUTURE,
  280. EXCEPTION_FUTURE,
  281. SUCCESSFUL_FUTURE,
  282. future1, future2],
  283. timeout=1.5,
  284. return_when=futures.ALL_COMPLETED)
  285. self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE,
  286. EXCEPTION_FUTURE,
  287. SUCCESSFUL_FUTURE,
  288. future1]), finished)
  289. self.assertEqual(set([future2]), pending)
  290. class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests):
  291. def test_pending_calls_race(self):
  292. # Issue #14406: multi-threaded race condition when waiting on all
  293. # futures.
  294. event = threading.Event()
  295. def future_func():
  296. event.wait()
  297. oldswitchinterval = sys.getcheckinterval()
  298. sys.setcheckinterval(1)
  299. try:
  300. fs = set(self.executor.submit(future_func) for i in range(100))
  301. event.set()
  302. futures.wait(fs, return_when=futures.ALL_COMPLETED)
  303. finally:
  304. sys.setcheckinterval(oldswitchinterval)
  305. class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests):
  306. pass
  307. class AsCompletedTests(unittest.TestCase):
  308. # TODO(brian@sweetapp.com): Should have a test with a non-zero timeout.
  309. def test_no_timeout(self):
  310. future1 = self.executor.submit(mul, 2, 21)
  311. future2 = self.executor.submit(mul, 7, 6)
  312. completed = set(futures.as_completed(
  313. [CANCELLED_AND_NOTIFIED_FUTURE,
  314. EXCEPTION_FUTURE,
  315. SUCCESSFUL_FUTURE,
  316. future1, future2]))
  317. self.assertEqual(set(
  318. [CANCELLED_AND_NOTIFIED_FUTURE,
  319. EXCEPTION_FUTURE,
  320. SUCCESSFUL_FUTURE,
  321. future1, future2]),
  322. completed)
  323. def test_zero_timeout(self):
  324. future1 = self.executor.submit(time.sleep, 2)
  325. completed_futures = set()
  326. try:
  327. for future in futures.as_completed(
  328. [CANCELLED_AND_NOTIFIED_FUTURE,
  329. EXCEPTION_FUTURE,
  330. SUCCESSFUL_FUTURE,
  331. future1],
  332. timeout=0):
  333. completed_futures.add(future)
  334. except futures.TimeoutError:
  335. pass
  336. self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE,
  337. EXCEPTION_FUTURE,
  338. SUCCESSFUL_FUTURE]),
  339. completed_futures)
  340. def test_duplicate_futures(self):
  341. # Issue 20367. Duplicate futures should not raise exceptions or give
  342. # duplicate responses.
  343. future1 = self.executor.submit(time.sleep, 2)
  344. completed = [f for f in futures.as_completed([future1,future1])]
  345. self.assertEqual(len(completed), 1)
  346. class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests):
  347. pass
  348. class ProcessPoolAsCompletedTests(ProcessPoolMixin, AsCompletedTests):
  349. pass
  350. class ExecutorTest(unittest.TestCase):
  351. # Executor.shutdown() and context manager usage is tested by
  352. # ExecutorShutdownTest.
  353. def test_submit(self):
  354. future = self.executor.submit(pow, 2, 8)
  355. self.assertEqual(256, future.result())
  356. def test_submit_keyword(self):
  357. future = self.executor.submit(mul, 2, y=8)
  358. self.assertEqual(16, future.result())
  359. def test_map(self):
  360. self.assertEqual(
  361. list(self.executor.map(pow, range(10), range(10))),
  362. list(map(pow, range(10), range(10))))
  363. def test_map_exception(self):
  364. i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5])
  365. self.assertEqual(next(i), (0, 1))
  366. self.assertEqual(next(i), (0, 1))
  367. self.assertRaises(ZeroDivisionError, next, i)
  368. def test_map_timeout(self):
  369. results = []
  370. try:
  371. for i in self.executor.map(time.sleep,
  372. [0, 0, 3],
  373. timeout=1.5):
  374. results.append(i)
  375. except futures.TimeoutError:
  376. pass
  377. else:
  378. self.fail('expected TimeoutError')
  379. self.assertEqual([None, None], results)
  380. class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest):
  381. def test_map_submits_without_iteration(self):
  382. """Tests verifying issue 11777."""
  383. finished = []
  384. def record_finished(n):
  385. finished.append(n)
  386. self.executor.map(record_finished, range(10))
  387. self.executor.shutdown(wait=True)
  388. self.assertEqual(len(finished), 10)
  389. class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest):
  390. pass
  391. class FutureTests(unittest.TestCase):
  392. def test_done_callback_with_result(self):
  393. callback_result = [None]
  394. def fn(callback_future):
  395. callback_result[0] = callback_future.result()
  396. f = Future()
  397. f.add_done_callback(fn)
  398. f.set_result(5)
  399. self.assertEqual(5, callback_result[0])
  400. def test_done_callback_with_exception(self):
  401. callback_exception = [None]
  402. def fn(callback_future):
  403. callback_exception[0] = callback_future.exception()
  404. f = Future()
  405. f.add_done_callback(fn)
  406. f.set_exception(Exception('test'))
  407. self.assertEqual(('test',), callback_exception[0].args)
  408. def test_done_callback_with_cancel(self):
  409. was_cancelled = [None]
  410. def fn(callback_future):
  411. was_cancelled[0] = callback_future.cancelled()
  412. f = Future()
  413. f.add_done_callback(fn)
  414. self.assertTrue(f.cancel())
  415. self.assertTrue(was_cancelled[0])
  416. def test_done_callback_raises(self):
  417. with captured_stderr() as stderr:
  418. raising_was_called = [False]
  419. fn_was_called = [False]
  420. def raising_fn(callback_future):
  421. raising_was_called[0] = True
  422. raise Exception('doh!')
  423. def fn(callback_future):
  424. fn_was_called[0] = True
  425. f = Future()
  426. f.add_done_callback(raising_fn)
  427. f.add_done_callback(fn)
  428. f.set_result(5)
  429. self.assertTrue(raising_was_called)
  430. self.assertTrue(fn_was_called)
  431. self.assertIn('Exception: doh!', stderr.getvalue())
  432. def test_done_callback_already_successful(self):
  433. callback_result = [None]
  434. def fn(callback_future):
  435. callback_result[0] = callback_future.result()
  436. f = Future()
  437. f.set_result(5)
  438. f.add_done_callback(fn)
  439. self.assertEqual(5, callback_result[0])
  440. def test_done_callback_already_failed(self):
  441. callback_exception = [None]
  442. def fn(callback_future):
  443. callback_exception[0] = callback_future.exception()
  444. f = Future()
  445. f.set_exception(Exception('test'))
  446. f.add_done_callback(fn)
  447. self.assertEqual(('test',), callback_exception[0].args)
  448. def test_done_callback_already_cancelled(self):
  449. was_cancelled = [None]
  450. def fn(callback_future):
  451. was_cancelled[0] = callback_future.cancelled()
  452. f = Future()
  453. self.assertTrue(f.cancel())
  454. f.add_done_callback(fn)
  455. self.assertTrue(was_cancelled[0])
  456. def test_repr(self):
  457. self.assertRegexpMatches(repr(PENDING_FUTURE),
  458. '<Future at 0x[0-9a-f]+ state=pending>')
  459. self.assertRegexpMatches(repr(RUNNING_FUTURE),
  460. '<Future at 0x[0-9a-f]+ state=running>')
  461. self.assertRegexpMatches(repr(CANCELLED_FUTURE),
  462. '<Future at 0x[0-9a-f]+ state=cancelled>')
  463. self.assertRegexpMatches(repr(CANCELLED_AND_NOTIFIED_FUTURE),
  464. '<Future at 0x[0-9a-f]+ state=cancelled>')
  465. self.assertRegexpMatches(
  466. repr(EXCEPTION_FUTURE),
  467. '<Future at 0x[0-9a-f]+ state=finished raised IOError>')
  468. self.assertRegexpMatches(
  469. repr(SUCCESSFUL_FUTURE),
  470. '<Future at 0x[0-9a-f]+ state=finished returned int>')
  471. def test_cancel(self):
  472. f1 = create_future(state=PENDING)
  473. f2 = create_future(state=RUNNING)
  474. f3 = create_future(state=CANCELLED)
  475. f4 = create_future(state=CANCELLED_AND_NOTIFIED)
  476. f5 = create_future(state=FINISHED, exception=IOError())
  477. f6 = create_future(state=FINISHED, result=5)
  478. self.assertTrue(f1.cancel())
  479. self.assertEqual(f1._state, CANCELLED)
  480. self.assertFalse(f2.cancel())
  481. self.assertEqual(f2._state, RUNNING)
  482. self.assertTrue(f3.cancel())
  483. self.assertEqual(f3._state, CANCELLED)
  484. self.assertTrue(f4.cancel())
  485. self.assertEqual(f4._state, CANCELLED_AND_NOTIFIED)
  486. self.assertFalse(f5.cancel())
  487. self.assertEqual(f5._state, FINISHED)
  488. self.assertFalse(f6.cancel())
  489. self.assertEqual(f6._state, FINISHED)
  490. def test_cancelled(self):
  491. self.assertFalse(PENDING_FUTURE.cancelled())
  492. self.assertFalse(RUNNING_FUTURE.cancelled())
  493. self.assertTrue(CANCELLED_FUTURE.cancelled())
  494. self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.cancelled())
  495. self.assertFalse(EXCEPTION_FUTURE.cancelled())
  496. self.assertFalse(SUCCESSFUL_FUTURE.cancelled())
  497. def test_done(self):
  498. self.assertFalse(PENDING_FUTURE.done())
  499. self.assertFalse(RUNNING_FUTURE.done())
  500. self.assertTrue(CANCELLED_FUTURE.done())
  501. self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.done())
  502. self.assertTrue(EXCEPTION_FUTURE.done())
  503. self.assertTrue(SUCCESSFUL_FUTURE.done())
  504. def test_running(self):
  505. self.assertFalse(PENDING_FUTURE.running())
  506. self.assertTrue(RUNNING_FUTURE.running())
  507. self.assertFalse(CANCELLED_FUTURE.running())
  508. self.assertFalse(CANCELLED_AND_NOTIFIED_FUTURE.running())
  509. self.assertFalse(EXCEPTION_FUTURE.running())
  510. self.assertFalse(SUCCESSFUL_FUTURE.running())
  511. def test_result_with_timeout(self):
  512. self.assertRaises(futures.TimeoutError,
  513. PENDING_FUTURE.result, timeout=0)
  514. self.assertRaises(futures.TimeoutError,
  515. RUNNING_FUTURE.result, timeout=0)
  516. self.assertRaises(futures.CancelledError,
  517. CANCELLED_FUTURE.result, timeout=0)
  518. self.assertRaises(futures.CancelledError,
  519. CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0)
  520. self.assertRaises(IOError, EXCEPTION_FUTURE.result, timeout=0)
  521. self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
  522. def test_result_with_success(self):
  523. # TODO(brian@sweetapp.com): This test is timing dependant.
  524. def notification():
  525. # Wait until the main thread is waiting for the result.
  526. time.sleep(1)
  527. f1.set_result(42)
  528. f1 = create_future(state=PENDING)
  529. t = threading.Thread(target=notification)
  530. t.start()
  531. self.assertEqual(f1.result(timeout=5), 42)
  532. def test_result_with_cancel(self):
  533. # TODO(brian@sweetapp.com): This test is timing dependant.
  534. def notification():
  535. # Wait until the main thread is waiting for the result.
  536. time.sleep(1)
  537. f1.cancel()
  538. f1 = create_future(state=PENDING)
  539. t = threading.Thread(target=notification)
  540. t.start()
  541. self.assertRaises(futures.CancelledError, f1.result, timeout=5)
  542. def test_exception_with_timeout(self):
  543. self.assertRaises(futures.TimeoutError,
  544. PENDING_FUTURE.exception, timeout=0)
  545. self.assertRaises(futures.TimeoutError,
  546. RUNNING_FUTURE.exception, timeout=0)
  547. self.assertRaises(futures.CancelledError,
  548. CANCELLED_FUTURE.exception, timeout=0)
  549. self.assertRaises(futures.CancelledError,
  550. CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0)
  551. self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0),
  552. IOError))
  553. self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None)
  554. def test_exception_with_success(self):
  555. def notification():
  556. # Wait until the main thread is waiting for the exception.
  557. time.sleep(1)
  558. with f1._condition:
  559. f1._state = FINISHED
  560. f1._exception = IOError()
  561. f1._condition.notify_all()
  562. f1 = create_future(state=PENDING)
  563. t = threading.Thread(target=notification)
  564. t.start()
  565. self.assertTrue(isinstance(f1.exception(timeout=5), IOError))
  566. @reap_threads
  567. def test_main():
  568. try:
  569. test_support.run_unittest(ProcessPoolExecutorTest,
  570. ThreadPoolExecutorTest,
  571. ProcessPoolWaitTests,
  572. ThreadPoolWaitTests,
  573. ProcessPoolAsCompletedTests,
  574. ThreadPoolAsCompletedTests,
  575. FutureTests,
  576. ProcessPoolShutdownTest,
  577. ThreadPoolShutdownTest)
  578. finally:
  579. test_support.reap_children()
  580. if __name__ == "__main__":
  581. test_main()