even more, better failing tests for thread_raise

This commit is contained in:
Noah Levitt 2017-05-16 14:00:10 -07:00
parent d2525e2e87
commit d514eaec15
2 changed files with 73 additions and 46 deletions

View File

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

View File

@ -192,31 +192,12 @@ def test_start_stop_backwards_compat():
assert not 'started' in job
assert not 'finished' in job
def test_thread_raise():
thread_caught_exception = None
class Exception1(Exception):
pass
class Exception2(Exception):
pass
def accept_immediately():
try:
with brozzler.thread_accept_exceptions():
brozzler.sleep(2)
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
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
class Exception1(Exception):
pass
class Exception2(Exception):
pass
def test_thread_raise_not_accept():
def never_accept():
try:
brozzler.sleep(2)
@ -224,42 +205,50 @@ def test_thread_raise():
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=never_accept)
th.start()
brozzler.thread_raise(th, Exception)
brozzler.thread_raise(th, Exception1)
th.join()
assert thread_caught_exception is None
def test_thread_raise_immediate():
def accept_immediately():
try:
with brozzler.thread_accept_exceptions():
brozzler.sleep(2)
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
# test immediate exception raise
thread_caught_exception = None
th = threading.Thread(target=accept_immediately)
th.start()
brozzler.thread_raise(th, Exception)
brozzler.thread_raise(th, Exception1)
start = time.time()
th.join()
assert thread_caught_exception
assert isinstance(thread_caught_exception, Exception1)
assert time.time() - start < 1.0
def test_thread_raise_safe_exit():
def delay_context_exit():
gate = brozzler.thread_accept_exceptions()
orig_exit = type(gate).__exit__
try:
type(gate).__exit__ = lambda self, et, ev, t: (
brozzler.sleep(2), orig_exit(self, et, ev, t), False)[-1]
with brozzler.thread_accept_exceptions() as gate:
brozzler.sleep(2)
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
finally:
type(gate).__exit__ = orig_exit
# test that a second thread_raise() doesn't result in an exception in
# ThreadExceptionGate.__exit__
thread_caught_exception = None
@ -273,13 +262,51 @@ def test_thread_raise():
assert thread_caught_exception
assert isinstance(thread_caught_exception, Exception1)
def test_thread_raise_pending_exception():
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
# 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)
brozzler.thread_raise(th, Exception1)
start = time.time()
th.join()
assert thread_caught_exception
assert isinstance(thread_caught_exception, Exception1)
assert time.time() - start > 1.0
def test_thread_raise_second_with_block():
def two_with_blocks():
try:
with brozzler.thread_accept_exceptions():
time.sleep(2)
return # test fails
except Exception1 as e:
pass
except:
return # fail test
try:
with brozzler.thread_accept_exceptions():
brozzler.sleep(2)
except Exception as e:
nonlocal thread_caught_exception
thread_caught_exception = e
# test that second `with` block gets second exception raised during first
# `with` block
thread_caught_exception = None
th = threading.Thread(target=two_with_blocks)
th.start()
brozzler.thread_raise(th, Exception1)
brozzler.thread_raise(th, Exception2)
th.join()
assert isinstance(thread_caught_exception, Exception2)