diff --git a/tests/test_exception_handling.py b/tests/test_exception_handling.py new file mode 100644 index 00000000..3a403f9a --- /dev/null +++ b/tests/test_exception_handling.py @@ -0,0 +1,155 @@ + +from unittest2 import TestCase +from collections import defaultdict + +from zipline.test_algorithms import ExceptionAlgorithm, DivByZeroAlgorithm, \ + InitializeTimeoutAlgorithm, TooMuchProcessingAlgorithm +from zipline.finance.trading import SIMULATION_STYLE +from zipline.core.devsimulator import AddressAllocator +from zipline.lines import SimulatedTrading +from zipline.gens.transform import StatefulTransform +from zipline.utils.timeout import TimeoutException + +from zipline.utils.test_utils import ( + drain_zipline, + setup_logger, + teardown_logger, + ExceptionSource, + ExceptionTransform +) + +DEFAULT_TIMEOUT = 15 # seconds +EXTENDED_TIMEOUT = 90 + +allocator = AddressAllocator(1000) + +class ExceptionTestCase(TestCase): + + leased_sockets = defaultdict(list) + + def setUp(self): + self.zipline_test_config = { + 'sid' : 133, + 'simulation_style' : SIMULATION_STYLE.FIXED_SLIPPAGE + } + setup_logger(self) + + def tearDown(self): + teardown_logger(self) + + def test_datasource_exception(self): + self.zipline_test_config['trade_source'] = ExceptionSource() + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(ZeroDivisionError) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual( + ctx.exception.message, + 'integer division or modulo by zero' + ) + + + def test_tranform_exception(self): + exc_tnfm = StatefulTransform(ExceptionTransform) + self.zipline_test_config['transforms'] = [exc_tnfm] + + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(AssertionError) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual(ctx.exception.message,'An assertion message') + + def test_exception_in_init(self): + # Simulation + # ---------- + self.zipline_test_config['algorithm'] = \ + ExceptionAlgorithm( + 'initialize', + self.zipline_test_config['sid'] + ) + + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(Exception) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual(ctx.exception.message,'Algo exception in initialize') + + def test_exception_in_handle_data(self): + # Simulation + # ---------- + self.zipline_test_config['algorithm'] = \ + ExceptionAlgorithm( + 'handle_data', + self.zipline_test_config['sid'] + ) + + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(Exception) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual(ctx.exception.message,'Algo exception in handle_data') + + def test_zerodivision_exception_in_handle_data(self): + + # Simulation + # ---------- + self.zipline_test_config['algorithm'] = \ + DivByZeroAlgorithm( + self.zipline_test_config['sid'] + ) + + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(ZeroDivisionError) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual(ctx.exception.message,'integer division or modulo by zero') + + + def test_initialize_timeout(self): + + self.zipline_test_config['algorithm'] = \ + InitializeTimeoutAlgorithm( + self.zipline_test_config['sid'] + ) + + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(TimeoutException) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual(ctx.exception.message,'Call to initialize timed out') + + def test_heartbeat(self): + + self.zipline_test_config['algorithm'] = \ + TooMuchProcessingAlgorithm( + self.zipline_test_config['sid'] + ) + zipline = SimulatedTrading.create_test_zipline( + **self.zipline_test_config + ) + + with self.assertRaises(TimeoutException) as ctx: + output, _ = drain_zipline(self, zipline) + + self.assertEqual( + ctx.exception.message, + 'Too much time spent in handle_data call' + ) diff --git a/zipline/test_algorithms.py b/zipline/test_algorithms.py index eb883469..62c78ffb 100644 --- a/zipline/test_algorithms.py +++ b/zipline/test_algorithms.py @@ -229,7 +229,8 @@ class InitializeTimeoutAlgorithm(): def initialize(self): import time from zipline.gens.tradesimulation import INIT_TIMEOUT - time.sleep(INIT_TIMEOUT + 1) + time.sleep(INIT_TIMEOUT + 1000) + def set_order(self, order_callable): pass @@ -245,7 +246,7 @@ class InitializeTimeoutAlgorithm(): def get_sid_filter(self): return [self.sid] - + class TooMuchProcessingAlgorithm(): def __init__(self, sid): self.sid = sid @@ -270,7 +271,7 @@ class TooMuchProcessingAlgorithm(): def get_sid_filter(self): return [self.sid] - + class TimeoutAlgorithm(): def __init__(self, sid): diff --git a/zipline/utils/test_utils.py b/zipline/utils/test_utils.py index ad085ba4..7d80cefe 100644 --- a/zipline/utils/test_utils.py +++ b/zipline/utils/test_utils.py @@ -62,7 +62,7 @@ def check(test, a, b, label=None): test.assertEqual(a, b, "mismatch on path: " + label) -def assert_single_position(test, zipline): +def drain_zipline(test, zipline): output = [] transaction_count = 0 msg_counter = 0 @@ -74,6 +74,12 @@ def assert_single_position(test, zipline): transaction_count += \ len(update['daily_perf']['transactions']) + return output, transaction_count + + +def assert_single_position(test, zipline): + + output, transaction_count = drain_zipline(test, zipline) test.assertEqual( test.zipline_test_config['order_count'], @@ -99,18 +105,6 @@ def assert_single_position(test, zipline): ) -def launch_component(component): - proc = multiprocessing.Process(target=component.run) - proc.start() - return proc - - -def launch_monitor(monitor): - proc = multiprocessing.Process(target=monitor.run) - proc.start() - return proc - - class ExceptionSource(object): def __init__(self):