def test_submit_request_context(self): test_value = random.randint(1, 101) executor = Executor(self.app) with self.app.test_request_context(''): request.test_value = test_value future = executor.submit(request_context_test_value) assert future.result() == test_value
def test_submit_app_context(self): test_value = random.randint(1, 101) self.app.config['TEST_VALUE'] = test_value executor = Executor(self.app) with self.app.test_request_context(''): future = executor.submit(app_context_test_value) assert future.result() == test_value
def test_coerce_config_types(self): self.app.config['EXECUTOR_MAX_WORKERS'] = '5' self.app.config['EXECUTOR_FUTURES_MAX_LENGTH'] = '10' self.app.config['EXECUTOR_PROPAGATE_EXCEPTIONS'] = 'true' executor = Executor(self.app) with self.app.test_request_context(): future = executor.submit_stored('fibonacci', fib, 35)
def test_executor_stored_future(self): executor = Executor(self.app) with self.app.test_request_context(): future = executor.submit_stored('fibonacci', fib, 35) assert executor.futures.done('fibonacci') is False assert future in executor.futures executor.futures.pop('fibonacci') assert future not in executor.futures
def test_propagate_exception_callback(self): self.app.config['EXECUTOR_PROPAGATE_EXCEPTIONS'] = True executor = Executor(self.app) with self.assertRaises(RuntimeError): with self.app.test_request_context('/'): future = executor.submit(fail) assert propagate_exceptions_callback in future._done_callbacks concurrent.futures.wait([future]) propagate_exceptions_callback(future)
def test_map_request_context(self): test_value = random.randint(1, 101) iterator = list(range(5)) executor = Executor(self.app) with self.app.test_request_context('/'): request.test_value = test_value results = executor.map(request_context_test_value, iterator) for r in results: assert r == test_value
def test_map_app_context(self): test_value = random.randint(1, 101) iterator = list(range(5)) self.app.config['TEST_VALUE'] = test_value executor = Executor(self.app) with self.app.test_request_context(''): results = executor.map(app_context_test_value, iterator) for r in results: assert r == test_value
def test_default_done_callback(self): executor = Executor(self.app) def callback(future): setattr(future, 'test', 'test') executor.add_default_done_callback(callback) with self.app.test_request_context('/'): future = executor.submit(fib, 5) concurrent.futures.wait([future]) assert hasattr(future, 'test')
def test_pre_init_executor(self): executor = Executor() @executor.job def decorated(n): return fib(n) assert executor executor.init_app(self.app) with self.app.test_request_context(''): future = decorated.submit(5) assert future.result() == fib(5)
def test_future_proxy(self): app = Flask(__name__) executor = Executor(app) with app.test_request_context(''): future = executor.submit(pow, 2, 4) # Test if we're returning a subclass of Future assert isinstance(future, concurrent.futures.Future) assert isinstance(future, FutureProxy) concurrent.futures.wait([future]) # test standard Future methods and attributes assert future._state == concurrent.futures._base.FINISHED assert future.done() assert future.exception(timeout=0) is None
def test_named_executor(self): name = 'custom' EXECUTOR_MAX_WORKERS = 5 CUSTOM_EXECUTOR_MAX_WORKERS = 10 self.app.config['EXECUTOR_MAX_WORKERS'] = EXECUTOR_MAX_WORKERS self.app.config[ 'CUSTOM_EXECUTOR_MAX_WORKERS'] = CUSTOM_EXECUTOR_MAX_WORKERS executor = Executor(self.app) custom_executor = Executor(self.app, name=name) assert 'executor' in self.app.extensions assert name + 'executor' in self.app.extensions assert executor._self._max_workers == EXECUTOR_MAX_WORKERS assert executor._max_workers == EXECUTOR_MAX_WORKERS assert custom_executor._self._max_workers == CUSTOM_EXECUTOR_MAX_WORKERS assert custom_executor._max_workers == CUSTOM_EXECUTOR_MAX_WORKERS
def test_init(self): self.app = Flask(__name__) executor = Executor(self.app) assert 'executor' in self.app.extensions assert isinstance(executor, concurrent.futures._base.Executor) assert isinstance(executor._self, concurrent.futures._base.Executor) assert getattr(executor, 'shutdown')
def test_thread_executor_init(self): self.app = Flask(__name__) self.app.config['EXECUTOR_TYPE'] = 'thread' executor = Executor(self.app) assert isinstance(executor._self, concurrent.futures.ThreadPoolExecutor) assert isinstance(executor, concurrent.futures.ThreadPoolExecutor)
def test_process_executor_init(self): self.app = Flask(__name__) self.app.config['EXECUTOR_TYPE'] = 'process' executor = Executor(self.app) assert isinstance(executor._self, concurrent.futures.ProcessPoolExecutor) assert isinstance(executor, concurrent.futures.ProcessPoolExecutor)
def test_max_workers(self): self.app = Flask(__name__) EXECUTOR_MAX_WORKERS = 10 self.app.config['EXECUTOR_MAX_WORKERS'] = EXECUTOR_MAX_WORKERS executor = Executor(self.app) assert executor._max_workers == EXECUTOR_MAX_WORKERS assert executor._self._max_workers == EXECUTOR_MAX_WORKERS
def test_named_executor_name(self): name = 'invalid name' try: executor = Executor(self.app, name=name) except ValueError: assert True else: assert False
def test_invalid_executor_init(self): self.app = Flask(__name__) self.app.config['EXECUTOR_TYPE'] = 'invalid_value' try: executor = Executor(self.app) except ValueError: assert True else: assert False
def test_thread_decorator_submit(self): self.app.config['EXECUTOR_TYPE'] = 'thread' executor = Executor(self.app) @executor.job def decorated(n): return fib(n) with self.app.test_request_context(''): future = decorated.submit(5) assert future.result() == fib(5)
def test_add_done_callback(self): """Exceptions thrown in callbacks can't be easily caught and make it hard to test for callback failure. To combat this, a global variable is used to store the value of an exception and test for its existence. """ app = Flask(__name__) executor = Executor(app) global exception exception = None with app.test_request_context(''): future = executor.submit(time.sleep, 0.5) def callback(future): global exception try: executor.submit(time.sleep, 0) except RuntimeError as e: exception = e future.add_done_callback(callback) concurrent.futures.wait([future]) assert exception is None
def test_process_decorator(self): ''' Using decorators should fail with a TypeError when using the ProcessPoolExecutor ''' self.app.config['EXECUTOR_TYPE'] = 'process' executor = Executor(self.app) try: @executor.job def decorated(n): return fib(n) except TypeError: pass else: assert 0
def test_thread_decorator_map(self): iterable = list(range(5)) self.app.config['EXECUTOR_TYPE'] = 'thread' executor = Executor(self.app) @executor.job def decorated(n): return fib(n) with self.app.test_request_context(''): results = decorated.map(iterable) for i, r in zip(iterable, results): assert fib(i) == r
def test_thread_decorator_submit_stored(self): self.app.config['EXECUTOR_TYPE'] = 'thread' executor = Executor(self.app) @executor.job def decorated(n): return fib(n) with self.app.test_request_context(): future = decorated.submit_stored('fibonacci', 35) assert executor.futures.done('fibonacci') is False assert future in executor.futures executor.futures.pop('fibonacci') assert future not in executor.futures
def test_submit(self): self.app = Flask(__name__) executor = Executor(self.app) with self.app.test_request_context(''): future = executor.submit(fib, 5) assert future.result() == fib(5)
def test_set_max_futures(self): self.app.config['EXECUTOR_FUTURES_MAX_LENGTH'] = 10 executor = Executor(self.app) assert executor.futures.max_length == self.app.config[ 'EXECUTOR_FUTURES_MAX_LENGTH']
def test_default_executor_init(self): self.app = Flask(__name__) executor = Executor(self.app) assert isinstance(executor._self, concurrent.futures.ThreadPoolExecutor)
def test_named_executor_submit(self): name = 'custom' custom_executor = Executor(self.app, name=name) with self.app.test_request_context(''): future = custom_executor.submit(fib, 5) assert future.result() == fib(5)
def test_factory_init(self): self.app = Flask(__name__) executor = Executor() executor.init_app(self.app) assert 'executor' in self.app.extensions assert isinstance(executor._self, concurrent.futures._base.Executor)
def test_shutdown_executor(self): executor = Executor(self.app) assert executor._shutdown is False executor.shutdown() assert executor._shutdown is True