コード例 #1
0
    def test_states_consistent(self):
        # Triples (state, running, stopped).
        states = []

        def record_states(event=None):
            states.append((
                self.executor.state,
                self.executor.running,
                self.executor.stopped,
            ))

        self.executor.observe(record_states, "running")
        self.executor.observe(record_states, "stopped")
        self.executor.observe(record_states, "state")
        submit_call(self.executor, int)

        # Record states before, during, and after stopping.
        record_states()
        self.executor.stop()
        self.wait_until_stopped(self.executor)
        record_states()

        for state, running, stopped in states:
            self.assertEqual(running, state == RUNNING)
            self.assertEqual(stopped, state == STOPPED)
コード例 #2
0
    def test_running_and_stopped_fired_only_once(self):
        submit_call(self.executor, int)
        self.executor.stop()
        self.wait_until_stopped(self.executor)

        self.assertEqual(self.listener.running_changes, [(True, False)])
        self.assertEqual(self.listener.stopped_changes, [(False, True)])
コード例 #3
0
    def test_shutdown_waits_for_background_tasks(self):
        starting = self._context.event()
        stopping = self._context.event()
        submit_call(self.executor, slow_call, starting, stopping)

        # Make sure background task has started, else it might be
        # cancelled altogether.
        self.assertTrue(starting.wait(timeout=SAFETY_TIMEOUT))

        self.executor.shutdown(timeout=SAFETY_TIMEOUT)
        self.assertTrue(stopping.is_set())
コード例 #4
0
    def test_cant_submit_new_unless_running(self):
        with self.long_running_task(self.executor):
            self.executor.stop()
            self.assertEqual(self.executor.state, STOPPING)

            with self.assertRaises(RuntimeError):
                submit_call(self.executor, len, (1, 2, 3))

        self.wait_until_stopped(self.executor)
        self.assertEqual(self.executor.state, STOPPED)
        with self.assertRaises(RuntimeError):
            submit_call(self.executor, int)
コード例 #5
0
    def test_double_cancel_variant(self):
        signal = self._context.event()
        test_ready = self._context.event()

        future = submit_call(self.executor, ping_pong, signal, test_ready)
        listener = CallFutureListener(future=future)

        # Wait for executing state; the test_ready event ensures we
        # get no further.
        self.assertTrue(signal.wait(timeout=TIMEOUT))
        self.wait_for_state(future, EXECUTING)

        self.assertTrue(future.cancellable)
        future.cancel()
        test_ready.set()

        self.assertFalse(future.cancellable)
        cancelled = future.cancel()
        self.assertFalse(cancelled)

        self.wait_until_done(future)

        self.assertNoResult(future)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, EXECUTING, CANCELLING, CANCELLED],
        )
コード例 #6
0
 def _submit_background_call(self, event):
     # Returns immediately.
     input = self.input
     self.input_for_calculation = self.input
     self.message = "Calculating square of {} ...".format(input)
     self.future = submit_call(self.traits_executor, slow_square, input)
     # Keep a record so that we can present messages accurately.
     self.input_for_calculation = input
コード例 #7
0
    def test_my_future(self):
        future = submit_call(self.traits_executor, pow, 3, 5)

        # Wait for the future to complete.
        self.assertEventuallyTrueInGui(lambda: future.done,
                                       timeout=SAFETY_TIMEOUT)

        self.assertEqual(future.result, 243)
コード例 #8
0
    def test_stop_with_multiple_futures(self):
        futures = []
        for i in range(100):
            futures.append(submit_call(self.executor, str, i))

        self.executor.stop()
        self.wait_until_stopped(self.executor)

        for future in futures:
            self.assertEqual(future.state, CANCELLED)
コード例 #9
0
 def target(executor, msg_queue):
     """
     Submit a simple callable to the given executor, and report
     the result of that submission to a queue.
     """
     try:
         future = submit_call(executor, pow, 2, 3)
     except BaseException as exc:
         msg_queue.put(("FAILED", exc))
     else:
         msg_queue.put(("DONE", future))
コード例 #10
0
    def test_failed_call(self):
        future = submit_call(self.executor, fail)
        listener = CallFutureListener(future=future)

        self.wait_until_done(future)

        self.assertNoResult(future)
        self.assertException(future, ZeroDivisionError)
        self.assertEqual(
            listener.states,
            [WAITING, EXECUTING, FAILED],
        )
コード例 #11
0
    def test_successful_call(self):
        future = submit_call(self.executor, pow, 2, 3)
        listener = CallFutureListener(future=future)

        self.wait_until_done(future)

        self.assertResult(future, 8)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, EXECUTING, COMPLETED],
        )
コード例 #12
0
    def test_multiple_futures(self):
        futures = []
        for i in range(100):
            futures.append(submit_call(self.executor, str, i))

        listener = FuturesListener(futures=futures)

        # Wait for all futures to complete.
        self.run_until(listener, "all_done",
                       lambda listener: listener.all_done)

        for i, future in enumerate(futures):
            self.assertEqual(future.result, str(i))
コード例 #13
0
    def test_cannot_cancel_after_success(self):
        future = submit_call(self.executor, pow, 2, 3)
        listener = CallFutureListener(future=future)

        self.wait_until_done(future)

        self.assertFalse(future.cancellable)
        cancelled = future.cancel()
        self.assertFalse(cancelled)

        self.assertResult(future, 8)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, EXECUTING, COMPLETED],
        )
コード例 #14
0
    def test_cannot_cancel_after_failure(self):
        future = submit_call(self.executor, fail)
        listener = CallFutureListener(future=future)

        self.wait_until_done(future)

        self.assertFalse(future.cancellable)
        cancelled = future.cancel()
        self.assertFalse(cancelled)

        self.assertNoResult(future)
        self.assertException(future, ZeroDivisionError)
        self.assertEqual(
            listener.states,
            [WAITING, EXECUTING, FAILED],
        )
コード例 #15
0
    def test_cancellation_before_execution(self):
        # Case where cancellation occurs before the future even starts
        # executing.
        with self.block_worker_pool():
            future = submit_call(self.executor, pow, 2, 3)
            listener = CallFutureListener(future=future)
            self.assertTrue(future.cancellable)
            future.cancel()

        self.wait_until_done(future)

        self.assertNoResult(future)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, CANCELLING, CANCELLED],
        )
コード例 #16
0
    def long_running_task(self, executor, timeout=SAFETY_TIMEOUT):
        """
        Simulate a long-running task being submitted to the executor.

        This context manager waits for the task to start executing before
        yielding the future associated to that task. The task will be
        terminated either at timeout or on exit of the associated with block.
        """
        started = self._context.event()
        event = self._context.event()
        try:
            future = submit_call(executor, wait_for_event, started, event,
                                 timeout)
            self.assertTrue(started.wait(timeout=timeout))
            yield future
        finally:
            event.set()
コード例 #17
0
    def test_run_until_timeout_trait_fired(self):
        # Trait fired, but condition still never true.
        executor = TraitsExecutor(
            context=MultithreadingContext(),
            event_loop=self._event_loop,
        )
        future = submit_call(executor, int, "111")
        start_time = time.monotonic()
        with self.assertRaises(RuntimeError):
            self.run_until(
                future,
                "state",
                condition=lambda future: future.state == CANCELLED,
                timeout=0.1,
            )
        actual_timeout = time.monotonic() - start_time

        executor.shutdown(timeout=SAFETY_TIMEOUT)
        self.assertLess(actual_timeout, 1.0)
コード例 #18
0
    def test_cannot_cancel_after_cancel(self):
        future = submit_call(self.executor, pow, 2, 3)
        listener = CallFutureListener(future=future)

        self.assertTrue(future.cancellable)
        cancelled = future.cancel()
        self.assertTrue(cancelled)
        self.assertFalse(future.cancellable)
        cancelled = future.cancel()
        self.assertFalse(cancelled)
        self.assertFalse(future.cancellable)

        self.wait_until_done(future)

        self.assertNoResult(future)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, CANCELLING, CANCELLED],
        )
コード例 #19
0
    def test_cancellation_vs_started_race_condition(self):
        # Simulate situation where a STARTED message arrives post-cancellation.
        event = self._context.event()

        future = submit_call(self.executor, event.set)
        listener = CallFutureListener(future=future)

        # Ensure the background task is past the cancellation check.
        self.assertTrue(event.wait(timeout=TIMEOUT))

        # And _now_ cancel before we process any messages.
        self.assertTrue(future.cancellable)
        future.cancel()
        self.wait_until_done(future)

        self.assertNoResult(future)
        self.assertNoException(future)
        self.assertEqual(
            listener.states,
            [WAITING, CANCELLING, CANCELLED],
        )
コード例 #20
0
    def test_run_until_success(self):
        # Trait fired, condition starts false but becomes true.
        executor = TraitsExecutor(
            context=MultithreadingContext(),
            event_loop=self._event_loop,
        )

        # Case 1: condition true on second trait change event.
        future = submit_call(executor, slow_return)
        self.run_until(
            future,
            "state",
            condition=lambda future: future.done,
        )
        self.assertTrue(future.done)

        # Case 2: condition true on the first trait firing.
        executor.stop()
        self.run_until(
            executor,
            "stopped",
            condition=lambda executor: executor.stopped,
        )
        self.assertTrue(executor.stopped)
コード例 #21
0
 def _submit_background_call(self, event):
     SlowCallDialog(
         future=submit_call(self.traits_executor, fibonacci, self.input),
         title=f"Calculating Fib({self.input}). Please wait.",
     ).open()
コード例 #22
0
 def _do_slow_square(self, event):
     future = submit_call(self.traits_executor, slow_square, self.input)
     self.current_futures.append(future)
コード例 #23
0
 def _submit_calculation(self, event):
     self.message = "Calculating π"
     self.future = submit_call(self.traits_executor, approximate_pi,
                               self.sample_count)
コード例 #24
0
 def test_shutdown_cancels_running_futures(self):
     future = submit_call(self.executor, pow, 3, 5)
     self.executor.shutdown(timeout=SAFETY_TIMEOUT)
     self.assertEqual(future.state, CANCELLED)
     self.assertTrue(self.executor.stopped)
コード例 #25
0
 def test_no_future_updates_after_shutdown(self):
     future = submit_call(self.executor, pow, 3, 5)
     self.executor.shutdown(timeout=SAFETY_TIMEOUT)
     self.assertEqual(future.state, CANCELLED)
     self.exercise_event_loop()
     self.assertEqual(future.state, CANCELLED)