Go to the documentation of this file.00001
00002 from __future__ import absolute_import, division, with_statement
00003
00004 from tornado.stack_context import StackContext, wrap
00005 from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, LogTrapTestCase
00006 from tornado.util import b
00007 from tornado.web import asynchronous, Application, RequestHandler
00008 import contextlib
00009 import functools
00010 import logging
00011 import unittest
00012
00013
00014 class TestRequestHandler(RequestHandler):
00015 def __init__(self, app, request, io_loop):
00016 super(TestRequestHandler, self).__init__(app, request)
00017 self.io_loop = io_loop
00018
00019 @asynchronous
00020 def get(self):
00021 logging.info('in get()')
00022
00023
00024 self.io_loop.add_callback(self.part2)
00025
00026 def part2(self):
00027 logging.info('in part2()')
00028
00029
00030 self.io_loop.add_callback(self.part3)
00031
00032 def part3(self):
00033 logging.info('in part3()')
00034 raise Exception('test exception')
00035
00036 def get_error_html(self, status_code, **kwargs):
00037 if 'exception' in kwargs and str(kwargs['exception']) == 'test exception':
00038 return 'got expected exception'
00039 else:
00040 return 'unexpected failure'
00041
00042
00043 class HTTPStackContextTest(AsyncHTTPTestCase, LogTrapTestCase):
00044 def get_app(self):
00045 return Application([('/', TestRequestHandler,
00046 dict(io_loop=self.io_loop))])
00047
00048 def test_stack_context(self):
00049 self.http_client.fetch(self.get_url('/'), self.handle_response)
00050 self.wait()
00051 self.assertEqual(self.response.code, 500)
00052 self.assertTrue(b('got expected exception') in self.response.body)
00053
00054 def handle_response(self, response):
00055 self.response = response
00056 self.stop()
00057
00058
00059 class StackContextTest(AsyncTestCase, LogTrapTestCase):
00060 def setUp(self):
00061 super(StackContextTest, self).setUp()
00062 self.active_contexts = []
00063
00064 @contextlib.contextmanager
00065 def context(self, name):
00066 self.active_contexts.append(name)
00067 yield
00068 self.assertEqual(self.active_contexts.pop(), name)
00069
00070
00071
00072 def test_exit_library_context(self):
00073 def library_function(callback):
00074
00075 callback = wrap(callback)
00076 with StackContext(functools.partial(self.context, 'library')):
00077 self.io_loop.add_callback(
00078 functools.partial(library_inner_callback, callback))
00079
00080 def library_inner_callback(callback):
00081 self.assertEqual(self.active_contexts[-2:],
00082 ['application', 'library'])
00083 callback()
00084
00085 def final_callback():
00086
00087
00088
00089
00090 self.assertEqual(self.active_contexts[-1], 'application')
00091 self.stop()
00092 with StackContext(functools.partial(self.context, 'application')):
00093 library_function(final_callback)
00094 self.wait()
00095
00096 def test_deactivate(self):
00097 deactivate_callbacks = []
00098
00099 def f1():
00100 with StackContext(functools.partial(self.context, 'c1')) as c1:
00101 deactivate_callbacks.append(c1)
00102 self.io_loop.add_callback(f2)
00103
00104 def f2():
00105 with StackContext(functools.partial(self.context, 'c2')) as c2:
00106 deactivate_callbacks.append(c2)
00107 self.io_loop.add_callback(f3)
00108
00109 def f3():
00110 with StackContext(functools.partial(self.context, 'c3')) as c3:
00111 deactivate_callbacks.append(c3)
00112 self.io_loop.add_callback(f4)
00113
00114 def f4():
00115 self.assertEqual(self.active_contexts, ['c1', 'c2', 'c3'])
00116 deactivate_callbacks[1]()
00117
00118
00119 self.assertEqual(self.active_contexts, ['c1', 'c2', 'c3'])
00120 self.io_loop.add_callback(f5)
00121
00122 def f5():
00123 self.assertEqual(self.active_contexts, ['c1', 'c3'])
00124 self.stop()
00125 self.io_loop.add_callback(f1)
00126 self.wait()
00127
00128 if __name__ == '__main__':
00129 unittest.main()