Пример #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)
    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))
    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],
        )
    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))
    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],
        )
    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],
        )
    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()
    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)
    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],
        )
    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],
        )
    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)
 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)