failing test for forthcoming behavior of thread_raise

This commit is contained in:
Noah Levitt 2017-05-15 16:20:20 -07:00
parent 60c5a7c1c4
commit d2525e2e87
2 changed files with 74 additions and 36 deletions

View File

@ -32,7 +32,7 @@ def find_package_data(package):
setuptools.setup(
name='brozzler',
version='1.1b11.dev245',
version='1.1b11.dev246',
description='Distributed web crawling with browsers',
url='https://github.com/internetarchive/brozzler',
author='Noah Levitt',

View File

@ -193,55 +193,93 @@ def test_start_stop_backwards_compat():
assert not 'finished' in job
def test_thread_raise():
let_thread_finish = threading.Event()
thread_preamble_done = threading.Event()
thread_caught_exception = None
def thread_target(accept_exceptions=False):
class Exception1(Exception):
pass
class Exception2(Exception):
pass
def accept_immediately():
try:
if accept_exceptions:
with brozzler.thread_accept_exceptions():
thread_preamble_done.set()
logging.info('waiting (accepting exceptions)')
let_thread_finish.wait()
else:
thread_preamble_done.set()
logging.info('waiting (not accepting exceptions)')
let_thread_finish.wait()
brozzler.sleep(2)
except Exception as e:
logging.info('caught exception %s', repr(e))
nonlocal thread_caught_exception
thread_caught_exception = e
finally:
logging.info('finishing')
let_thread_finish.clear()
thread_preamble_done.clear()
# test that thread_raise does not raise exception in a thread that has not
# called thread_accept_exceptions
def accept_eventually():
try:
brozzler.sleep(2)
with brozzler.thread_accept_exceptions():
pass
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
def never_accept():
try:
brozzler.sleep(2)
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
def delay_context_exit():
try:
with brozzler.thread_accept_exceptions() as gate:
logging.info('gate=%s', gate)
orig_exit = gate.__exit__
import traceback
gate.__exit__ = lambda et, ev, t: (
logging.info('fake exit'), traceback.print_stack(),
brozzler.sleep(2), orig_exit(et, ev, t))
try:
brozzler.sleep(2)
except Exception as e:
raise
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
# test that thread_raise does not raise exception in a thread that has no
# `with thread_exception_gate()` block
thread_caught_exception = None
th = threading.Thread(target=lambda: thread_target(accept_exceptions=False))
th = threading.Thread(target=never_accept)
th.start()
thread_preamble_done.wait()
with pytest.raises(TypeError):
brozzler.thread_raise(
th, Exception("i'm an instance, which is not allowed"))
assert brozzler.thread_raise(th, Exception) is False
assert thread_caught_exception is None
let_thread_finish.set()
brozzler.thread_raise(th, Exception)
th.join()
assert thread_caught_exception is None
# test that thread_raise raises exception in a thread that has called
# thread_accept_exceptions
# test immediate exception raise
thread_caught_exception = None
th = threading.Thread(target=lambda: thread_target(accept_exceptions=True))
th = threading.Thread(target=accept_immediately)
th.start()
thread_preamble_done.wait()
assert brozzler.thread_raise(th, Exception) is True
let_thread_finish.set()
brozzler.thread_raise(th, Exception)
start = time.time()
th.join()
assert thread_caught_exception
with pytest.raises(threading.ThreadError): # thread is not running
brozzler.thread_raise(th, Exception)
assert time.time() - start < 1.0
# test that a second thread_raise() doesn't result in an exception in
# ThreadExceptionGate.__exit__
thread_caught_exception = None
th = threading.Thread(target=delay_context_exit)
th.start()
time.sleep(0.2)
brozzler.thread_raise(th, Exception1)
time.sleep(0.2)
brozzler.thread_raise(th, Exception2)
th.join()
assert thread_caught_exception
assert isinstance(thread_caught_exception, Exception1)
# test exception that has to wait for `with thread_exception_gate()` block
thread_caught_exception = None
th = threading.Thread(target=accept_eventually)
th.start()
brozzler.thread_raise(th, Exception)
start = time.time()
th.join()
assert thread_caught_exception
assert time.time() - start > 1.0