from tornado.netutil import ssl_options_to_context
from tornado.simple_httpclient import SimpleAsyncHTTPClient
from tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog, gen_test # noqa: E501
-from tornado.test.util import unittest, skipOnTravis, ignore_deprecation
+from tornado.test.util import unittest, skipOnTravis
from tornado.web import Application, RequestHandler, stream_request_body
from contextlib import closing
def raw_fetch(self, headers, body, newline=b"\r\n"):
with closing(IOStream(socket.socket())) as stream:
- with ignore_deprecation():
- stream.connect(('127.0.0.1', self.get_http_port()), self.stop)
- self.wait()
+ self.io_loop.run_sync(lambda: stream.connect(('127.0.0.1', self.get_http_port())))
stream.write(
newline.join(headers +
[utf8("Content-Length: %d" % len(body))]) +
from tornado.web import RequestHandler, Application
import errno
import hashlib
-import logging
import os
import platform
import random
@gen_test
def test_write_while_connecting(self):
stream = self._make_client_iostream()
- connected = [False]
- cond = Condition()
-
- def connected_callback():
- connected[0] = True
- cond.notify()
- with ignore_deprecation():
- stream.connect(("127.0.0.1", self.get_http_port()),
- callback=connected_callback)
+ connect_fut = stream.connect(("127.0.0.1", self.get_http_port()))
# unlike the previous tests, try to write before the connection
# is complete.
- written = [False]
+ write_fut = stream.write(b"GET / HTTP/1.0\r\nConnection: close\r\n\r\n")
+ self.assertFalse(connect_fut.done())
- def write_callback():
- written[0] = True
- cond.notify()
- with ignore_deprecation():
- stream.write(b"GET / HTTP/1.0\r\nConnection: close\r\n\r\n",
- callback=write_callback)
- self.assertTrue(not connected[0])
- # by the time the write has flushed, the connection callback has
- # also run
- try:
- while not (connected[0] and written[0]):
- yield cond.wait()
- finally:
- logging.debug((connected, written))
+ # connect will always complete before write.
+ it = gen.WaitIterator(connect_fut, write_fut)
+ resolved_order = []
+ while not it.done():
+ yield it.next()
+ resolved_order.append(it.current_future)
+ self.assertEqual(resolved_order, [connect_fut, write_fut])
data = yield stream.read_until_close()
self.assertTrue(data.endswith(b"Hello"))
self.assertEqual(res, OK)
ws.close()
- with ignore_deprecation():
- rs.read_until(b"\r\n", lambda x: x)
+ rs.read_until(b"\r\n")
# If _close_callback (self.stop) is not called,
# an AssertionError: Async operation timed out after 5 seconds
# will be raised.
rs.close()
@gen_test
- def test_read_until_max_bytes_inline(self):
+ def test_read_until_max_bytes_inline_legacy(self):
rs, ws = yield self.make_iostream_pair()
closed = Event()
rs.set_close_callback(closed.set)
ws.close()
rs.close()
+ @gen_test
+ def test_read_until_max_bytes_inline(self):
+ rs, ws = yield self.make_iostream_pair()
+ closed = Event()
+ rs.set_close_callback(closed.set)
+ try:
+ # Similar to the error case in the previous test, but the
+ # ws writes first so rs reads are satisfied
+ # inline. For consistency with the out-of-line case, we
+ # do not raise the error synchronously.
+ ws.write(b"123456")
+ with ExpectLog(gen_log, "Unsatisfiable read"):
+ with self.assertRaises(StreamClosedError):
+ yield rs.read_until(b"def", max_bytes=5)
+ yield closed.wait()
+ finally:
+ ws.close()
+ rs.close()
+
@gen_test
def test_read_until_max_bytes_ignores_extra(self):
rs, ws = yield self.make_iostream_pair()
listener.close()
raise gen.Return((server_stream, client_stream))
- def test_connection_refused(self):
+ def test_connection_refused_legacy(self):
# When a connection is refused, the connect callback should not
# be run. (The kqueue IOLoop used to behave differently from the
# epoll IOLoop in this respect)
# cygwin's errnos don't match those used on native windows python
self.assertTrue(stream.error.args[0] in _ERRNO_CONNREFUSED)
+ @gen_test
+ def test_connection_refused(self):
+ # When a connection is refused, the connect callback should not
+ # be run. (The kqueue IOLoop used to behave differently from the
+ # epoll IOLoop in this respect)
+ cleanup_func, port = refusing_port()
+ self.addCleanup(cleanup_func)
+ stream = IOStream(socket.socket())
+
+ stream.set_close_callback(self.stop)
+ # log messages vary by platform and ioloop implementation
+ with ExpectLog(gen_log, ".*", required=False):
+ with self.assertRaises(StreamClosedError):
+ yield stream.connect(("127.0.0.1", port))
+
+ self.assertTrue(isinstance(stream.error, socket.error), stream.error)
+ if sys.platform != 'cygwin':
+ _ERRNO_CONNREFUSED = (errno.ECONNREFUSED,)
+ if hasattr(errno, "WSAECONNREFUSED"):
+ _ERRNO_CONNREFUSED += (errno.WSAECONNREFUSED,)
+ # cygwin's errnos don't match those used on native windows python
+ self.assertTrue(stream.error.args[0] in _ERRNO_CONNREFUSED)
+
@unittest.skipIf(mock is None, 'mock package not present')
+ @gen_test
def test_gaierror(self):
# Test that IOStream sets its exc_info on getaddrinfo error.
# It's difficult to reliably trigger a getaddrinfo error;
stream.set_close_callback(self.stop)
with mock.patch('socket.socket.connect',
side_effect=socket.gaierror(errno.EIO, 'boom')):
- with ExpectLog(gen_log, "Connect error"):
- with ignore_deprecation():
- stream.connect(('localhost', 80), callback=self.stop)
- self.wait()
- self.assertIsInstance(stream.error, socket.gaierror)
+ with self.assertRaises(StreamClosedError):
+ yield stream.connect(('localhost', 80))
+ self.assertTrue(isinstance(stream.error, socket.gaierror))
@gen_test
def test_read_callback_error(self):
with mock.patch('tornado.iostream.BaseIOStream._try_inline_read',
side_effect=IOError('boom')):
with self.assertRaisesRegexp(IOError, 'boom'):
- with ignore_deprecation():
- client.read_until_close(lambda x: None)
+ client.read_until_close()
finally:
server.close()
client.close()
server.set_close_callback(closed.set)
try:
# Start a read that will be fulfilled asynchronously.
- with ignore_deprecation():
- server.read_bytes(1, lambda data: None)
+ server.read_bytes(1)
client.write(b'a')
# Stub out read_from_fd to make it fail.
handshake_future = Future()
class TestServer(TCPServer):
+ @gen.coroutine
def handle_stream(self, stream, address):
- with ignore_deprecation():
- stream.wait_for_handshake(self.handshake_done)
+ fut = stream.wait_for_handshake()
test.assertRaises(RuntimeError, stream.wait_for_handshake)
+ yield fut
- def handshake_done(self):
handshake_future.set_result(None)
yield self.connect_to_server(TestServer)
handshake_future = Future()
class TestServer(TCPServer):
+ @gen.coroutine
def handle_stream(self, stream, address):
- self.stream = stream
- with ignore_deprecation():
- stream.wait_for_handshake(self.handshake_done)
-
- def handshake_done(self):
- with ignore_deprecation():
- self.stream.wait_for_handshake(self.handshake2_done)
-
- def handshake2_done(self):
+ yield stream.wait_for_handshake()
+ yield stream.wait_for_handshake()
handshake_future.set_result(None)
yield self.connect_to_server(TestServer)
from tornado.test import httpclient_test
from tornado.testing import (AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase,
ExpectLog, gen_test)
-from tornado.test.util import (skipOnTravis, skipIfNoIPv6, refusing_port, skipBefore35,
- exec_test, ignore_deprecation)
+from tornado.test.util import skipOnTravis, skipIfNoIPv6, refusing_port, skipBefore35, exec_test
from tornado.web import RequestHandler, Application, url, stream_request_body
@gen_test
def test_connect_timeout(self):
timeout = 0.1
- timeout_min, timeout_max = 0.099, 1.0
class TimeoutResolver(Resolver):
def resolve(self, *args, **kwargs):
return Future() # never completes
with closing(self.create_client(resolver=TimeoutResolver())) as client:
- with ignore_deprecation():
- response = yield client.fetch(self.get_url('/hello'),
- connect_timeout=timeout,
- raise_error=False)
- self.assertEqual(response.code, 599)
- self.assertTrue(timeout_min < response.request_time < timeout_max,
- response.request_time)
- self.assertEqual(str(response.error), "Timeout while connecting")
+ with self.assertRaises(HTTPTimeoutError):
+ yield client.fetch(self.get_url('/hello'),
+ connect_timeout=timeout,
+ request_timeout=3600,
+ raise_error=True)
@skipOnTravis
def test_request_timeout(self):
timeout = 0.1
- timeout_min, timeout_max = 0.099, 0.15
if os.name == 'nt':
timeout = 0.5
- timeout_min, timeout_max = 0.4, 0.6
-
- with ignore_deprecation():
- response = self.fetch('/trigger?wake=false', request_timeout=timeout)
- self.assertEqual(response.code, 599)
- self.assertTrue(timeout_min < response.request_time < timeout_max,
- response.request_time)
- self.assertEqual(str(response.error), "Timeout during request")
+
+ with self.assertRaises(HTTPTimeoutError):
+ self.fetch('/trigger?wake=false', request_timeout=timeout, raise_error=True)
# trigger the hanging request to let it clean up after itself
self.triggers.popleft()()
cleanup_func, port = refusing_port()
self.addCleanup(cleanup_func)
with ExpectLog(gen_log, ".*", required=False):
- with ignore_deprecation():
- response = self.fetch("http://127.0.0.1:%d/" % port)
- self.assertEqual(599, response.code)
+ with self.assertRaises(socket.error) as cm:
+ self.fetch("http://127.0.0.1:%d/" % port, raise_error=True)
if sys.platform != 'cygwin':
# cygwin returns EPERM instead of ECONNREFUSED here
- contains_errno = str(errno.ECONNREFUSED) in str(response.error)
+ contains_errno = str(errno.ECONNREFUSED) in str(cm.exception)
if not contains_errno and hasattr(errno, "WSAECONNREFUSED"):
- contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)
- self.assertTrue(contains_errno, response.error)
+ contains_errno = str(errno.WSAECONNREFUSED) in str(cm.exception)
+ self.assertTrue(contains_errno, cm.exception)
# This is usually "Connection refused".
# On windows, strerror is broken and returns "Unknown error".
expected_message = os.strerror(errno.ECONNREFUSED)
- self.assertTrue(expected_message in str(response.error),
- response.error)
+ self.assertTrue(expected_message in str(cm.exception),
+ cm.exception)
def test_queue_timeout(self):
- with ignore_deprecation():
- with closing(self.create_client(max_clients=1)) as client:
- # Wait for the trigger request to block, not complete.
- fut1 = client.fetch(self.get_url('/trigger'),
- request_timeout=10, raise_error=False)
- self.wait()
- fut2 = client.fetch(self.get_url('/hello'),
- connect_timeout=0.1, raise_error=False)
- fut2.add_done_callback(self.stop)
- response = self.wait().result()
-
- self.assertEqual(response.code, 599)
- self.assertTrue(response.request_time < 1, response.request_time)
- self.assertEqual(str(response.error), "Timeout in request queue")
- self.triggers.popleft()()
- fut1.add_done_callback(self.stop)
- self.wait()
- fut1.result()
+ with closing(self.create_client(max_clients=1)) as client:
+ # Wait for the trigger request to block, not complete.
+ fut1 = client.fetch(self.get_url('/trigger'), request_timeout=10)
+ self.wait()
+ with self.assertRaises(HTTPTimeoutError) as cm:
+ self.io_loop.run_sync(lambda: client.fetch(
+ self.get_url('/hello'), connect_timeout=0.1, raise_error=True))
+
+ self.assertEqual(str(cm.exception), "Timeout in request queue")
+ self.triggers.popleft()()
+ self.io_loop.run_sync(lambda: fut1)
def test_no_content_length(self):
response = self.fetch("/no_content_length")
request.connection.finish()
return
self.request = request
- with ignore_deprecation():
- self.request.connection.stream.write(
- b"HTTP/1.1 100 CONTINUE\r\n\r\n",
- self.respond_200)
+ fut = self.request.connection.stream.write(
+ b"HTTP/1.1 100 CONTINUE\r\n\r\n")
+ fut.add_done_callback(self.respond_200)
- def respond_200(self):
- with ignore_deprecation():
- self.request.connection.stream.write(
- b"HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\nA",
- self.request.connection.stream.close)
+ def respond_200(self, fut):
+ fut.result()
+ fut = self.request.connection.stream.write(
+ b"HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\nA")
+ fut.add_done_callback(lambda f: self.request.connection.stream.close())
def get_app(self):
# Not a full Application, but works as an HTTPServer callback
def test_204_invalid_content_length(self):
# 204 status with non-zero content length is malformed
with ExpectLog(gen_log, ".*Response with code 204 should not have body"):
- with ignore_deprecation():
- response = self.fetch("/?error=1")
- if not self.http1:
- self.skipTest("requires HTTP/1.x")
- if self.http_client.configured_class != SimpleAsyncHTTPClient:
- self.skipTest("curl client accepts invalid headers")
- self.assertEqual(response.code, 599)
+ with self.assertRaises(HTTPStreamClosedError):
+ self.fetch("/?error=1", raise_error=True)
+ if not self.http1:
+ self.skipTest("requires HTTP/1.x")
+ if self.http_client.configured_class != SimpleAsyncHTTPClient:
+ self.skipTest("curl client accepts invalid headers")
class HostnameMappingTestCase(AsyncHTTPTestCase):
from tornado import gen, ioloop
from tornado.log import app_log
+from tornado.simple_httpclient import SimpleAsyncHTTPClient, HTTPTimeoutError
from tornado.test.util import unittest, skipBefore35, exec_test, ignore_deprecation
from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, bind_unused_port, gen_test, ExpectLog
from tornado.web import Application
response = self.fetch(path)
self.assertEqual(response.request.url, self.get_url(path))
+ @gen_test
def test_fetch_full_http_url(self):
path = 'http://localhost:%d/path' % self.external_port
- with ignore_deprecation():
- response = self.fetch(path, request_timeout=0.1, raise_error=False)
- self.assertEqual(response.request.url, path)
+ with contextlib.closing(SimpleAsyncHTTPClient(force_instance=True)) as client:
+ with self.assertRaises(HTTPTimeoutError) as cm:
+ yield client.fetch(path, request_timeout=0.1, raise_error=True)
+ self.assertEqual(cm.exception.response.request.url, path)
+ @gen_test
def test_fetch_full_https_url(self):
path = 'https://localhost:%d/path' % self.external_port
- with ignore_deprecation():
- response = self.fetch(path, request_timeout=0.1)
- self.assertEqual(response.request.url, path)
+ with contextlib.closing(SimpleAsyncHTTPClient(force_instance=True)) as client:
+ with self.assertRaises(HTTPTimeoutError) as cm:
+ yield client.fetch(path, request_timeout=0.1, raise_error=True)
+ self.assertEqual(cm.exception.response.request.url, path)
@classmethod
def tearDownClass(cls):
# Ensure that the flush callback is run whether or not there
# was any output. The gen.Task and direct yield forms are
# equivalent.
- with ignore_deprecation():
- yield gen.Task(self.flush) # "empty" flush, but writes headers
- yield gen.Task(self.flush) # empty flush
+ yield self.flush() # "empty" flush, but writes headers
+ yield self.flush() # empty flush
self.write("o")
yield self.flush() # flushes the "o"
yield self.flush() # empty flush
self.write('requires HTTP/1.x')
def test_client_close(self):
- with ignore_deprecation():
- response = self.fetch('/')
- if response.body == b'requires HTTP/1.x':
- self.skipTest('requires HTTP/1.x')
- self.assertEqual(response.code, 599)
+ with self.assertRaises((HTTPClientError, unittest.SkipTest)):
+ response = self.fetch('/', raise_error=True)
+ if response.body == b'requires HTTP/1.x':
+ self.skipTest('requires HTTP/1.x')
+ self.assertEqual(response.code, 599)
class SignedValueTest(unittest.TestCase):