util.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. from __future__ import absolute_import, division, print_function
  2. import contextlib
  3. import os
  4. import platform
  5. import socket
  6. import sys
  7. import textwrap
  8. import warnings
  9. from tornado.testing import bind_unused_port
  10. # Delegate the choice of unittest or unittest2 to tornado.testing.
  11. from tornado.testing import unittest
  12. skipIfNonUnix = unittest.skipIf(os.name != 'posix' or sys.platform == 'cygwin',
  13. "non-unix platform")
  14. # travis-ci.org runs our tests in an overworked virtual machine, which makes
  15. # timing-related tests unreliable.
  16. skipOnTravis = unittest.skipIf('TRAVIS' in os.environ,
  17. 'timing tests unreliable on travis')
  18. skipOnAppEngine = unittest.skipIf('APPENGINE_RUNTIME' in os.environ,
  19. 'not available on Google App Engine')
  20. # Set the environment variable NO_NETWORK=1 to disable any tests that
  21. # depend on an external network.
  22. skipIfNoNetwork = unittest.skipIf('NO_NETWORK' in os.environ,
  23. 'network access disabled')
  24. skipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 (yield from) not available')
  25. skipBefore35 = unittest.skipIf(sys.version_info < (3, 5), 'PEP 492 (async/await) not available')
  26. skipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',
  27. 'Not CPython implementation')
  28. # Used for tests affected by
  29. # https://bitbucket.org/pypy/pypy/issues/2616/incomplete-error-handling-in
  30. # TODO: remove this after pypy3 5.8 is obsolete.
  31. skipPypy3V58 = unittest.skipIf(platform.python_implementation() == 'PyPy' and
  32. sys.version_info > (3,) and
  33. sys.pypy_version_info < (5, 9),
  34. 'pypy3 5.8 has buggy ssl module')
  35. def _detect_ipv6():
  36. if not socket.has_ipv6:
  37. # socket.has_ipv6 check reports whether ipv6 was present at compile
  38. # time. It's usually true even when ipv6 doesn't work for other reasons.
  39. return False
  40. sock = None
  41. try:
  42. sock = socket.socket(socket.AF_INET6)
  43. sock.bind(('::1', 0))
  44. except socket.error:
  45. return False
  46. finally:
  47. if sock is not None:
  48. sock.close()
  49. return True
  50. skipIfNoIPv6 = unittest.skipIf(not _detect_ipv6(), 'ipv6 support not present')
  51. def refusing_port():
  52. """Returns a local port number that will refuse all connections.
  53. Return value is (cleanup_func, port); the cleanup function
  54. must be called to free the port to be reused.
  55. """
  56. # On travis-ci, port numbers are reassigned frequently. To avoid
  57. # collisions with other tests, we use an open client-side socket's
  58. # ephemeral port number to ensure that nothing can listen on that
  59. # port.
  60. server_socket, port = bind_unused_port()
  61. server_socket.setblocking(1)
  62. client_socket = socket.socket()
  63. client_socket.connect(("127.0.0.1", port))
  64. conn, client_addr = server_socket.accept()
  65. conn.close()
  66. server_socket.close()
  67. return (client_socket.close, client_addr[1])
  68. def exec_test(caller_globals, caller_locals, s):
  69. """Execute ``s`` in a given context and return the result namespace.
  70. Used to define functions for tests in particular python
  71. versions that would be syntax errors in older versions.
  72. """
  73. # Flatten the real global and local namespace into our fake
  74. # globals: it's all global from the perspective of code defined
  75. # in s.
  76. global_namespace = dict(caller_globals, **caller_locals) # type: ignore
  77. local_namespace = {}
  78. exec(textwrap.dedent(s), global_namespace, local_namespace)
  79. return local_namespace
  80. def subTest(test, *args, **kwargs):
  81. """Compatibility shim for unittest.TestCase.subTest.
  82. Usage: ``with tornado.test.util.subTest(self, x=x):``
  83. """
  84. try:
  85. subTest = test.subTest # py34+
  86. except AttributeError:
  87. subTest = contextlib.contextmanager(lambda *a, **kw: (yield))
  88. return subTest(*args, **kwargs)
  89. @contextlib.contextmanager
  90. def ignore_deprecation():
  91. """Context manager to ignore deprecation warnings."""
  92. with warnings.catch_warnings():
  93. warnings.simplefilter('ignore', DeprecationWarning)
  94. yield