mirror of
https://github.com/internetarchive/brozzler.git
synced 2025-06-20 12:54:23 -04:00
failing test for forthcoming behavior of thread_raise
This commit is contained in:
parent
60c5a7c1c4
commit
d2525e2e87
2 changed files with 74 additions and 36 deletions
2
setup.py
2
setup.py
|
@ -32,7 +32,7 @@ def find_package_data(package):
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name='brozzler',
|
name='brozzler',
|
||||||
version='1.1b11.dev245',
|
version='1.1b11.dev246',
|
||||||
description='Distributed web crawling with browsers',
|
description='Distributed web crawling with browsers',
|
||||||
url='https://github.com/internetarchive/brozzler',
|
url='https://github.com/internetarchive/brozzler',
|
||||||
author='Noah Levitt',
|
author='Noah Levitt',
|
||||||
|
|
|
@ -193,55 +193,93 @@ def test_start_stop_backwards_compat():
|
||||||
assert not 'finished' in job
|
assert not 'finished' in job
|
||||||
|
|
||||||
def test_thread_raise():
|
def test_thread_raise():
|
||||||
let_thread_finish = threading.Event()
|
|
||||||
thread_preamble_done = threading.Event()
|
|
||||||
thread_caught_exception = None
|
thread_caught_exception = None
|
||||||
|
|
||||||
def thread_target(accept_exceptions=False):
|
class Exception1(Exception):
|
||||||
|
pass
|
||||||
|
class Exception2(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def accept_immediately():
|
||||||
try:
|
try:
|
||||||
if accept_exceptions:
|
with brozzler.thread_accept_exceptions():
|
||||||
with brozzler.thread_accept_exceptions():
|
brozzler.sleep(2)
|
||||||
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()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('caught exception %s', repr(e))
|
|
||||||
nonlocal thread_caught_exception
|
nonlocal thread_caught_exception
|
||||||
thread_caught_exception = e
|
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
|
def accept_eventually():
|
||||||
# called thread_accept_exceptions
|
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
|
thread_caught_exception = None
|
||||||
th = threading.Thread(target=lambda: thread_target(accept_exceptions=False))
|
th = threading.Thread(target=never_accept)
|
||||||
th.start()
|
th.start()
|
||||||
thread_preamble_done.wait()
|
brozzler.thread_raise(th, Exception)
|
||||||
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()
|
|
||||||
th.join()
|
th.join()
|
||||||
assert thread_caught_exception is None
|
assert thread_caught_exception is None
|
||||||
|
|
||||||
# test that thread_raise raises exception in a thread that has called
|
# test immediate exception raise
|
||||||
# thread_accept_exceptions
|
|
||||||
thread_caught_exception = None
|
thread_caught_exception = None
|
||||||
th = threading.Thread(target=lambda: thread_target(accept_exceptions=True))
|
th = threading.Thread(target=accept_immediately)
|
||||||
th.start()
|
th.start()
|
||||||
thread_preamble_done.wait()
|
brozzler.thread_raise(th, Exception)
|
||||||
assert brozzler.thread_raise(th, Exception) is True
|
start = time.time()
|
||||||
let_thread_finish.set()
|
|
||||||
th.join()
|
th.join()
|
||||||
assert thread_caught_exception
|
assert thread_caught_exception
|
||||||
with pytest.raises(threading.ThreadError): # thread is not running
|
assert time.time() - start < 1.0
|
||||||
brozzler.thread_raise(th, Exception)
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue