mirror of
https://github.com/internetarchive/brozzler.git
synced 2025-02-23 16:19:49 -05:00
even more, better failing tests for thread_raise
This commit is contained in:
parent
d2525e2e87
commit
d514eaec15
2
setup.py
2
setup.py
@ -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',
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user