code: def gen_test(func=None, timeout=None):
      """Testing equivalent of ``@gen.coroutine``, to be applied to test methods.
  
      ``@gen.coroutine`` cannot be used on tests because the `.IOLoop` is not
      already running.  ``@gen_test`` should be applied to test methods
      on subclasses of `AsyncTestCase`.
  
      Example::
  
          class MyTest(AsyncHTTPTestCase):
              @gen_test
              def test_something(self):
                  response = yield gen.Task(self.fetch('/'))
  
      By default, ``@gen_test`` times out after 5 seconds. The timeout may be
      overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable,
      or for each test with the ``timeout`` keyword argument::
  
          class MyTest(AsyncHTTPTestCase):
              @gen_test(timeout=10)
              def test_something_slow(self):
                  response = yield gen.Task(self.fetch('/'))
  
      .. versionadded:: 3.1
         The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment
         variable.
  
      .. versionchanged:: 4.0
         The wrapper now passes along ``*args, **kwargs`` so it can be used
         on functions with arguments.
      """
      if timeout is None:
          timeout = get_async_test_timeout()
  
      def wrap(f):
          # Stack up several decorators to allow us to access the generator
          # object itself.  In the innermost wrapper, we capture the generator
          # and save it in an attribute of self.  Next, we run the wrapped
          # function through @gen.coroutine.  Finally, the coroutine is
          # wrapped again to make it synchronous with run_sync.
          #
          # This is a good case study arguing for either some sort of
          # extensibility in the gen decorators or cancellation support.
          @functools.wraps(f)
          def pre_coroutine(self, *args, **kwargs):
              result = f(self, *args, **kwargs)
              if isinstance(result, GeneratorType) or iscoroutine(
                  result
              ):
                  self._test_generator = result
              else:
                  self._test_generator = None
              return result
  
          if iscoroutinefunction(f):
              coro = pre_coroutine
          else:
              coro = gen.coroutine(pre_coroutine)
  
          @functools.wraps(coro)
          def post_coroutine(self, *args, **kwargs):
              try:
                  return self.io_loop.run_sync(
                      functools.partial(coro, self, *args, **kwargs),
                      timeout=timeout,
                  )
              except TimeoutError as e:
                  # run_sync raises an error with an unhelpful traceback.
                  # Throw it back into the generator or coroutine so the stack
                  # trace is replaced by the point where the test is stopped.
                  self._test_generator.throw(e)
                  # In case the test contains an overly broad except clause,
                  # we may get back here.  In this case re-raise the original
                  # exception, which is better than nothing.
                  raise
  
          return post_coroutine
  
      if func is not None:
          # Used like:
          #     @gen_test
          #     def f(self):
          #         pass
          return wrap(func)
      else:
          # Used like @gen_test(timeout=10)
          return wrap
  
imports: from __future__ import absolute_import, division, print_function
  from tornado.log import gen_log, app_log
  from tornado.stack_context import ExceptionStackContext
  from tornado.util import raise_exc_info, basestring_type, PY3
  import functools
  import inspect
  import logging
  import os
  import re
  import signal
  import socket
  import sys
label_desc: Use image node_id 4 for calling a global function with example usage: gen_test(func, timeout) and returns: post_coroutine, wrap, wrap, result, self