(root)/
Python-3.12.0/
Lib/
test/
test_concurrent_futures/
test_future.py
       1  import threading
       2  import time
       3  import unittest
       4  from concurrent import futures
       5  from concurrent.futures._base import (
       6      PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future)
       7  
       8  from test import support
       9  
      10  from .util import (
      11      PENDING_FUTURE, RUNNING_FUTURE, CANCELLED_FUTURE,
      12      CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE,
      13      BaseTestCase, create_future, setup_module)
      14  
      15  
      16  class ESC[4;38;5;81mFutureTests(ESC[4;38;5;149mBaseTestCase):
      17      def test_done_callback_with_result(self):
      18          callback_result = None
      19          def fn(callback_future):
      20              nonlocal callback_result
      21              callback_result = callback_future.result()
      22  
      23          f = Future()
      24          f.add_done_callback(fn)
      25          f.set_result(5)
      26          self.assertEqual(5, callback_result)
      27  
      28      def test_done_callback_with_exception(self):
      29          callback_exception = None
      30          def fn(callback_future):
      31              nonlocal callback_exception
      32              callback_exception = callback_future.exception()
      33  
      34          f = Future()
      35          f.add_done_callback(fn)
      36          f.set_exception(Exception('test'))
      37          self.assertEqual(('test',), callback_exception.args)
      38  
      39      def test_done_callback_with_cancel(self):
      40          was_cancelled = None
      41          def fn(callback_future):
      42              nonlocal was_cancelled
      43              was_cancelled = callback_future.cancelled()
      44  
      45          f = Future()
      46          f.add_done_callback(fn)
      47          self.assertTrue(f.cancel())
      48          self.assertTrue(was_cancelled)
      49  
      50      def test_done_callback_raises(self):
      51          with support.captured_stderr() as stderr:
      52              raising_was_called = False
      53              fn_was_called = False
      54  
      55              def raising_fn(callback_future):
      56                  nonlocal raising_was_called
      57                  raising_was_called = True
      58                  raise Exception('doh!')
      59  
      60              def fn(callback_future):
      61                  nonlocal fn_was_called
      62                  fn_was_called = True
      63  
      64              f = Future()
      65              f.add_done_callback(raising_fn)
      66              f.add_done_callback(fn)
      67              f.set_result(5)
      68              self.assertTrue(raising_was_called)
      69              self.assertTrue(fn_was_called)
      70              self.assertIn('Exception: doh!', stderr.getvalue())
      71  
      72      def test_done_callback_already_successful(self):
      73          callback_result = None
      74          def fn(callback_future):
      75              nonlocal callback_result
      76              callback_result = callback_future.result()
      77  
      78          f = Future()
      79          f.set_result(5)
      80          f.add_done_callback(fn)
      81          self.assertEqual(5, callback_result)
      82  
      83      def test_done_callback_already_failed(self):
      84          callback_exception = None
      85          def fn(callback_future):
      86              nonlocal callback_exception
      87              callback_exception = callback_future.exception()
      88  
      89          f = Future()
      90          f.set_exception(Exception('test'))
      91          f.add_done_callback(fn)
      92          self.assertEqual(('test',), callback_exception.args)
      93  
      94      def test_done_callback_already_cancelled(self):
      95          was_cancelled = None
      96          def fn(callback_future):
      97              nonlocal was_cancelled
      98              was_cancelled = callback_future.cancelled()
      99  
     100          f = Future()
     101          self.assertTrue(f.cancel())
     102          f.add_done_callback(fn)
     103          self.assertTrue(was_cancelled)
     104  
     105      def test_done_callback_raises_already_succeeded(self):
     106          with support.captured_stderr() as stderr:
     107              def raising_fn(callback_future):
     108                  raise Exception('doh!')
     109  
     110              f = Future()
     111  
     112              # Set the result first to simulate a future that runs instantly,
     113              # effectively allowing the callback to be run immediately.
     114              f.set_result(5)
     115              f.add_done_callback(raising_fn)
     116  
     117              self.assertIn('exception calling callback for', stderr.getvalue())
     118              self.assertIn('doh!', stderr.getvalue())
     119  
     120  
     121      def test_repr(self):
     122          self.assertRegex(repr(PENDING_FUTURE),
     123                           '<Future at 0x[0-9a-f]+ state=pending>')
     124          self.assertRegex(repr(RUNNING_FUTURE),
     125                           '<Future at 0x[0-9a-f]+ state=running>')
     126          self.assertRegex(repr(CANCELLED_FUTURE),
     127                           '<Future at 0x[0-9a-f]+ state=cancelled>')
     128          self.assertRegex(repr(CANCELLED_AND_NOTIFIED_FUTURE),
     129                           '<Future at 0x[0-9a-f]+ state=cancelled>')
     130          self.assertRegex(
     131                  repr(EXCEPTION_FUTURE),
     132                  '<Future at 0x[0-9a-f]+ state=finished raised OSError>')
     133          self.assertRegex(
     134                  repr(SUCCESSFUL_FUTURE),
     135                  '<Future at 0x[0-9a-f]+ state=finished returned int>')
     136  
     137      def test_cancel(self):
     138          f1 = create_future(state=PENDING)
     139          f2 = create_future(state=RUNNING)
     140          f3 = create_future(state=CANCELLED)
     141          f4 = create_future(state=CANCELLED_AND_NOTIFIED)
     142          f5 = create_future(state=FINISHED, exception=OSError())
     143          f6 = create_future(state=FINISHED, result=5)
     144  
     145          self.assertTrue(f1.cancel())
     146          self.assertEqual(f1._state, CANCELLED)
     147  
     148          self.assertFalse(f2.cancel())
     149          self.assertEqual(f2._state, RUNNING)
     150  
     151          self.assertTrue(f3.cancel())
     152          self.assertEqual(f3._state, CANCELLED)
     153  
     154          self.assertTrue(f4.cancel())
     155          self.assertEqual(f4._state, CANCELLED_AND_NOTIFIED)
     156  
     157          self.assertFalse(f5.cancel())
     158          self.assertEqual(f5._state, FINISHED)
     159  
     160          self.assertFalse(f6.cancel())
     161          self.assertEqual(f6._state, FINISHED)
     162  
     163      def test_cancelled(self):
     164          self.assertFalse(PENDING_FUTURE.cancelled())
     165          self.assertFalse(RUNNING_FUTURE.cancelled())
     166          self.assertTrue(CANCELLED_FUTURE.cancelled())
     167          self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.cancelled())
     168          self.assertFalse(EXCEPTION_FUTURE.cancelled())
     169          self.assertFalse(SUCCESSFUL_FUTURE.cancelled())
     170  
     171      def test_done(self):
     172          self.assertFalse(PENDING_FUTURE.done())
     173          self.assertFalse(RUNNING_FUTURE.done())
     174          self.assertTrue(CANCELLED_FUTURE.done())
     175          self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.done())
     176          self.assertTrue(EXCEPTION_FUTURE.done())
     177          self.assertTrue(SUCCESSFUL_FUTURE.done())
     178  
     179      def test_running(self):
     180          self.assertFalse(PENDING_FUTURE.running())
     181          self.assertTrue(RUNNING_FUTURE.running())
     182          self.assertFalse(CANCELLED_FUTURE.running())
     183          self.assertFalse(CANCELLED_AND_NOTIFIED_FUTURE.running())
     184          self.assertFalse(EXCEPTION_FUTURE.running())
     185          self.assertFalse(SUCCESSFUL_FUTURE.running())
     186  
     187      def test_result_with_timeout(self):
     188          self.assertRaises(futures.TimeoutError,
     189                            PENDING_FUTURE.result, timeout=0)
     190          self.assertRaises(futures.TimeoutError,
     191                            RUNNING_FUTURE.result, timeout=0)
     192          self.assertRaises(futures.CancelledError,
     193                            CANCELLED_FUTURE.result, timeout=0)
     194          self.assertRaises(futures.CancelledError,
     195                            CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0)
     196          self.assertRaises(OSError, EXCEPTION_FUTURE.result, timeout=0)
     197          self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
     198  
     199      def test_result_with_success(self):
     200          # TODO(brian@sweetapp.com): This test is timing dependent.
     201          def notification():
     202              # Wait until the main thread is waiting for the result.
     203              time.sleep(1)
     204              f1.set_result(42)
     205  
     206          f1 = create_future(state=PENDING)
     207          t = threading.Thread(target=notification)
     208          t.start()
     209  
     210          self.assertEqual(f1.result(timeout=5), 42)
     211          t.join()
     212  
     213      def test_result_with_cancel(self):
     214          # TODO(brian@sweetapp.com): This test is timing dependent.
     215          def notification():
     216              # Wait until the main thread is waiting for the result.
     217              time.sleep(1)
     218              f1.cancel()
     219  
     220          f1 = create_future(state=PENDING)
     221          t = threading.Thread(target=notification)
     222          t.start()
     223  
     224          self.assertRaises(futures.CancelledError,
     225                            f1.result, timeout=support.SHORT_TIMEOUT)
     226          t.join()
     227  
     228      def test_exception_with_timeout(self):
     229          self.assertRaises(futures.TimeoutError,
     230                            PENDING_FUTURE.exception, timeout=0)
     231          self.assertRaises(futures.TimeoutError,
     232                            RUNNING_FUTURE.exception, timeout=0)
     233          self.assertRaises(futures.CancelledError,
     234                            CANCELLED_FUTURE.exception, timeout=0)
     235          self.assertRaises(futures.CancelledError,
     236                            CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0)
     237          self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0),
     238                                     OSError))
     239          self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None)
     240  
     241      def test_exception_with_success(self):
     242          def notification():
     243              # Wait until the main thread is waiting for the exception.
     244              time.sleep(1)
     245              with f1._condition:
     246                  f1._state = FINISHED
     247                  f1._exception = OSError()
     248                  f1._condition.notify_all()
     249  
     250          f1 = create_future(state=PENDING)
     251          t = threading.Thread(target=notification)
     252          t.start()
     253  
     254          self.assertTrue(isinstance(f1.exception(timeout=support.SHORT_TIMEOUT), OSError))
     255          t.join()
     256  
     257      def test_multiple_set_result(self):
     258          f = create_future(state=PENDING)
     259          f.set_result(1)
     260  
     261          with self.assertRaisesRegex(
     262                  futures.InvalidStateError,
     263                  'FINISHED: <Future at 0x[0-9a-f]+ '
     264                  'state=finished returned int>'
     265          ):
     266              f.set_result(2)
     267  
     268          self.assertTrue(f.done())
     269          self.assertEqual(f.result(), 1)
     270  
     271      def test_multiple_set_exception(self):
     272          f = create_future(state=PENDING)
     273          e = ValueError()
     274          f.set_exception(e)
     275  
     276          with self.assertRaisesRegex(
     277                  futures.InvalidStateError,
     278                  'FINISHED: <Future at 0x[0-9a-f]+ '
     279                  'state=finished raised ValueError>'
     280          ):
     281              f.set_exception(Exception())
     282  
     283          self.assertEqual(f.exception(), e)
     284  
     285  
     286  def setUpModule():
     287      setup_module()
     288  
     289  
     290  if __name__ == "__main__":
     291      unittest.main()