{
    "file_diffs": [
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport ssl\nimport sys\n\nfrom tornado.escape import to_unicode\nfrom tornado import gen\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders, ResponseStartLine\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.concurrent import Future\nfrom tornado.netutil import Resolver, bind_sockets\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler, RedirectHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import skipOnTravis, skipIfNoIPv6, refusing_port, unittest, skipBefore35, exec_test\nfrom tornado.web import RequestHandler, Application, asynchronous, url, stream_request_body\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        self.set_status(204)\n        self.finish()\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass NoContentLengthHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        if self.request.version.startswith('HTTP/1'):\n            # Emulate the old HTTP/1.0 behavior of returning a body with no\n            # content-length.  Tornado handles content-length at the framework\n            # level so we have to go around it.\n            stream = self.request.connection.detach()\n            stream.write(b\"HTTP/1.0 200 OK\\r\\n\\r\\n\"\n                         b\"hello\")\n            stream.close()\n        else:\n            self.finish('HTTP/1 required')\n\n\nclass EchoPostHandler(RequestHandler):\n    def post(self):\n        self.write(self.request.body)\n\n\n@stream_request_body\nclass RespondInPrepareHandler(RequestHandler):\n    def prepare(self):\n        self.set_status(403)\n        self.finish(\"forbidden\")\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True, **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n    def test_ssl_options(self):\n        resp = self.fetch(\"/hello\", ssl_options={})\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_context(self):\n        resp = self.fetch(\"/hello\",\n                          ssl_options=ssl.SSLContext(ssl.PROTOCOL_SSLv23))\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_options_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\",\n                       required=False):\n            resp = self.fetch(\n                \"/hello\", ssl_options=dict(cert_reqs=ssl.CERT_REQUIRED))\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_ssl_context_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\"):\n            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n            ctx.verify_mode = ssl.CERT_REQUIRED\n            resp = self.fetch(\"/hello\", ssl_options=ctx)\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors (in this case,\n        # failure to validate the testing self-signed cert).\n        # The SSLError is exposed through ssl.SSLError.\n        with ExpectLog(gen_log, '.*') as expect_log:\n            response = self.fetch(\"/\", validate_cert=True)\n            self.assertEqual(response.code, 599)\n            self.assertIsInstance(response.error, ssl.SSLError)\n        self.assertFalse(expect_log.logged_stack)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(res.body, b'A')\n\n\nclass HTTP204NoContentTestCase(AsyncHTTPTestCase):\n    def respond_204(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            # Close the request cleanly in HTTP/2; it will be skipped anyway.\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n\n        # A 204 response never has a body, even if doesn't have a content-length\n        # (which would otherwise mean read-until-close).  We simulate here a\n        # server that sends no content length and does not close the connection.\n        #\n        # Tests of a 204 response with no Content-Length header are included\n        # in SimpleHTTPClientTestMixin.\n        stream = request.connection.detach()\n        stream.write(b\"HTTP/1.1 204 No content\\r\\n\")\n        if request.arguments.get(\"error\", [False])[-1]:\n            stream.write(b\"Content-Length: 5\\r\\n\")\n        else:\n            stream.write(b\"Content-Length: 0\\r\\n\")\n        stream.write(b\"\\r\\n\")\n        stream.close()\n\n    def get_app(self):\n        return self.respond_204\n\n    def test_204_no_content(self):\n        resp = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(resp.code, 204)\n        self.assertEqual(resp.body, b'')\n\n    def test_204_invalid_content_length(self):\n        # 204 status with non-zero content length is malformed\n        with ExpectLog(gen_log, \".*Response with code 204 should not have body\"):\n            response = self.fetch(\"/?error=1\")\n            if not self.http1:\n                self.skipTest(\"requires HTTP/1.x\")\n            if self.http_client.configured_class != SimpleAsyncHTTPClient:\n                self.skipTest(\"curl client accepts invalid headers\")\n            self.assertEqual(response.code, 599)\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass ResolveTimeoutTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        # Dummy Resolver subclass that never invokes its callback.\n        class BadResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                pass\n\n        super(ResolveTimeoutTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            resolver=BadResolver())\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_resolve_timeout(self):\n        response = self.fetch('/hello', connect_timeout=0.1)\n        self.assertEqual(response.code, 599)\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 100)\n                self.write(\"ok\")\n\n        class LargeHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 1000)\n                self.write(\"ok\")\n\n        return Application([('/small', SmallHeaders),\n                            ('/large', LargeHeaders)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'ok')\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBodySizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 64)\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/small', SmallBody),\n                            ('/large', LargeBody)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 64)\n\n    def test_small_body(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 64)\n\n    def test_large_body(self):\n        with ExpectLog(gen_log, \"Malformed HTTP message from None: Content-Length too long\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBufferSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/large', LargeBody)])\n\n    def get_http_client(self):\n        # 100KB body with 64KB buffer\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 100, max_buffer_size=1024 * 64)\n\n    def test_large_body(self):\n        response = self.fetch('/large')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 100)\n\n\nclass ChunkedWithContentLengthTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class ChunkedWithContentLength(RequestHandler):\n            def get(self):\n                # Add an invalid Transfer-Encoding to the response\n                self.set_header('Transfer-Encoding', 'chunked')\n                self.write(\"Hello world\")\n\n        return Application([('/chunkwithcl', ChunkedWithContentLength)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient()\n\n    def test_chunked_with_content_length(self):\n        # Make sure the invalid headers are detected\n        with ExpectLog(gen_log, (\"Malformed HTTP message from None: Response \"\n                                 \"with both Transfer-Encoding and Content-Length\")):\n            response = self.fetch('/chunkwithcl')\n        self.assertEqual(response.code, 599)\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport ssl\nimport sys\n\nfrom tornado.escape import to_unicode\nfrom tornado import gen\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders, ResponseStartLine\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.concurrent import Future\nfrom tornado.netutil import Resolver, bind_sockets\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler, RedirectHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import skipOnTravis, skipIfNoIPv6, refusing_port, unittest, skipBefore35, exec_test\nfrom tornado.web import RequestHandler, Application, asynchronous, url, stream_request_body\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        self.set_status(204)\n        self.finish()\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass NoContentLengthHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        if self.request.version.startswith('HTTP/1'):\n            # Emulate the old HTTP/1.0 behavior of returning a body with no\n            # content-length.  Tornado handles content-length at the framework\n            # level so we have to go around it.\n            stream = self.request.connection.detach()\n            stream.write(b\"HTTP/1.0 200 OK\\r\\n\\r\\n\"\n                         b\"hello\")\n            stream.close()\n        else:\n            self.finish('HTTP/1 required')\n\n\nclass EchoPostHandler(RequestHandler):\n    def post(self):\n        self.write(self.request.body)\n\n\n@stream_request_body\nclass RespondInPrepareHandler(RequestHandler):\n    def prepare(self):\n        self.set_status(403)\n        self.finish(\"forbidden\")\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n        port = sock.getsockname()[1]\n        self.http_server.add_socket(sock)\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^127.0.0.1:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True, **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n    def test_ssl_options(self):\n        resp = self.fetch(\"/hello\", ssl_options={})\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_context(self):\n        resp = self.fetch(\"/hello\",\n                          ssl_options=ssl.SSLContext(ssl.PROTOCOL_SSLv23))\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_options_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\",\n                       required=False):\n            resp = self.fetch(\n                \"/hello\", ssl_options=dict(cert_reqs=ssl.CERT_REQUIRED))\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_ssl_context_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\"):\n            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n            ctx.verify_mode = ssl.CERT_REQUIRED\n            resp = self.fetch(\"/hello\", ssl_options=ctx)\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors (in this case,\n        # failure to validate the testing self-signed cert).\n        # The SSLError is exposed through ssl.SSLError.\n        with ExpectLog(gen_log, '.*') as expect_log:\n            response = self.fetch(\"/\", validate_cert=True)\n            self.assertEqual(response.code, 599)\n            self.assertIsInstance(response.error, ssl.SSLError)\n        self.assertFalse(expect_log.logged_stack)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(res.body, b'A')\n\n\nclass HTTP204NoContentTestCase(AsyncHTTPTestCase):\n    def respond_204(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            # Close the request cleanly in HTTP/2; it will be skipped anyway.\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n\n        # A 204 response never has a body, even if doesn't have a content-length\n        # (which would otherwise mean read-until-close).  We simulate here a\n        # server that sends no content length and does not close the connection.\n        #\n        # Tests of a 204 response with no Content-Length header are included\n        # in SimpleHTTPClientTestMixin.\n        stream = request.connection.detach()\n        stream.write(b\"HTTP/1.1 204 No content\\r\\n\")\n        if request.arguments.get(\"error\", [False])[-1]:\n            stream.write(b\"Content-Length: 5\\r\\n\")\n        else:\n            stream.write(b\"Content-Length: 0\\r\\n\")\n        stream.write(b\"\\r\\n\")\n        stream.close()\n\n    def get_app(self):\n        return self.respond_204\n\n    def test_204_no_content(self):\n        resp = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(resp.code, 204)\n        self.assertEqual(resp.body, b'')\n\n    def test_204_invalid_content_length(self):\n        # 204 status with non-zero content length is malformed\n        with ExpectLog(gen_log, \".*Response with code 204 should not have body\"):\n            response = self.fetch(\"/?error=1\")\n            if not self.http1:\n                self.skipTest(\"requires HTTP/1.x\")\n            if self.http_client.configured_class != SimpleAsyncHTTPClient:\n                self.skipTest(\"curl client accepts invalid headers\")\n            self.assertEqual(response.code, 599)\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass ResolveTimeoutTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        # Dummy Resolver subclass that never invokes its callback.\n        class BadResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                pass\n\n        super(ResolveTimeoutTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            resolver=BadResolver())\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_resolve_timeout(self):\n        response = self.fetch('/hello', connect_timeout=0.1)\n        self.assertEqual(response.code, 599)\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 100)\n                self.write(\"ok\")\n\n        class LargeHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 1000)\n                self.write(\"ok\")\n\n        return Application([('/small', SmallHeaders),\n                            ('/large', LargeHeaders)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'ok')\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBodySizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 64)\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/small', SmallBody),\n                            ('/large', LargeBody)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 64)\n\n    def test_small_body(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 64)\n\n    def test_large_body(self):\n        with ExpectLog(gen_log, \"Malformed HTTP message from None: Content-Length too long\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBufferSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/large', LargeBody)])\n\n    def get_http_client(self):\n        # 100KB body with 64KB buffer\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 100, max_buffer_size=1024 * 64)\n\n    def test_large_body(self):\n        response = self.fetch('/large')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 100)\n\n\nclass ChunkedWithContentLengthTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class ChunkedWithContentLength(RequestHandler):\n            def get(self):\n                # Add an invalid Transfer-Encoding to the response\n                self.set_header('Transfer-Encoding', 'chunked')\n                self.write(\"Hello world\")\n\n        return Application([('/chunkwithcl', ChunkedWithContentLength)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient()\n\n    def test_chunked_with_content_length(self):\n        # Make sure the invalid headers are detected\n        with ExpectLog(gen_log, (\"Malformed HTTP message from None: Response \"\n                                 \"with both Transfer-Encoding and Content-Length\")):\n            response = self.fetch('/chunkwithcl')\n        self.assertEqual(response.code, 599)\n",
            "header": {
                "file": {
                    "path": "tornado/test/simple_httpclient_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "309678ef",
                "new_commit_hash": "df41abd7",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/simple_httpclient_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/simple_httpclient_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 271,
                            "length": 16
                        },
                        "new_range": {
                            "start": 271,
                            "length": 9
                        },
                        "section": "class SimpleHTTPClientTestMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @skipIfNoIPv6",
                                "type": "context"
                            },
                            {
                                "content": "    def test_ipv6(self):",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "deleted"
                            },
                            {
                                "content": "            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)",
                                "type": "deleted"
                            },
                            {
                                "content": "            port = sock.getsockname()[1]",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.http_server.add_socket(sock)",
                                "type": "deleted"
                            },
                            {
                                "content": "        except socket.gaierror as e:",
                                "type": "deleted"
                            },
                            {
                                "content": "            if e.args[0] == socket.EAI_ADDRFAMILY:",
                                "type": "deleted"
                            },
                            {
                                "content": "                # python supports ipv6, but it's not configured on the network",
                                "type": "deleted"
                            },
                            {
                                "content": "                # interface, so skip this test.",
                                "type": "deleted"
                            },
                            {
                                "content": "                return",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise",
                                "type": "deleted"
                            },
                            {
                                "content": "        [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)",
                                "type": "added"
                            },
                            {
                                "content": "        port = sock.getsockname()[1]",
                                "type": "added"
                            },
                            {
                                "content": "        self.http_server.add_socket(sock)",
                                "type": "added"
                            },
                            {
                                "content": "        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # ipv6 is currently enabled by default but can be disabled",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "class",
                            "name": "SimpleHTTPClientTestMixin",
                            "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 126,
                            "end_lineno": 474,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "method",
                            "name": "SimpleHTTPClientTestMixin.test_ipv6",
                            "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 273,
                            "end_lineno": 293,
                            "parent": {
                                "file_name": "tornado/test/simple_httpclient_test.py",
                                "type": "class",
                                "name": "SimpleHTTPClientTestMixin",
                                "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 126,
                                "end_lineno": 474,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 326,
                            "length": 7
                        },
                        "new_range": {
                            "start": 319,
                            "length": 7
                        },
                        "section": "class SimpleHTTPClientTestMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertNotIn(\"Content-Length\", response.headers)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_host_header(self):",
                                "type": "context"
                            },
                            {
                                "content": "        host_re = re.compile(b\"^localhost:[0-9]+$\")",
                                "type": "deleted"
                            },
                            {
                                "content": "        host_re = re.compile(b\"^127.0.0.1:[0-9]+$\")",
                                "type": "added"
                            },
                            {
                                "content": "        response = self.fetch(\"/host_echo\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertTrue(host_re.match(response.body))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "class",
                            "name": "SimpleHTTPClientTestMixin",
                            "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 126,
                            "end_lineno": 474,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "method",
                            "name": "SimpleHTTPClientTestMixin.test_host_header",
                            "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 328,
                            "end_lineno": 336,
                            "parent": {
                                "file_name": "tornado/test/simple_httpclient_test.py",
                                "type": "class",
                                "name": "SimpleHTTPClientTestMixin",
                                "content": "class SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        try:\n            [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n            port = sock.getsockname()[1]\n            self.http_server.add_socket(sock)\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 126,
                                "end_lineno": 474,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function\n\nimport contextlib\nimport os\nimport platform\nimport socket\nimport sys\nimport textwrap\n\nfrom tornado.testing import bind_unused_port\n\n# Delegate the choice of unittest or unittest2 to tornado.testing.\nfrom tornado.testing import unittest\n\nskipIfNonUnix = unittest.skipIf(os.name != 'posix' or sys.platform == 'cygwin',\n                                \"non-unix platform\")\n\n# travis-ci.org runs our tests in an overworked virtual machine, which makes\n# timing-related tests unreliable.\nskipOnTravis = unittest.skipIf('TRAVIS' in os.environ,\n                               'timing tests unreliable on travis')\n\nskipOnAppEngine = unittest.skipIf('APPENGINE_RUNTIME' in os.environ,\n                                  'not available on Google App Engine')\n\n# Set the environment variable NO_NETWORK=1 to disable any tests that\n# depend on an external network.\nskipIfNoNetwork = unittest.skipIf('NO_NETWORK' in os.environ,\n                                  'network access disabled')\n\nskipIfNoIPv6 = unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')\n\n\nskipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 (yield from) not available')\nskipBefore35 = unittest.skipIf(sys.version_info < (3, 5), 'PEP 492 (async/await) not available')\nskipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',\n                                 'Not CPython implementation')\n\n# Used for tests affected by\n# https://bitbucket.org/pypy/pypy/issues/2616/incomplete-error-handling-in\n# TODO: remove this after pypy3 5.8 is obsolete.\nskipPypy3V58 = unittest.skipIf(platform.python_implementation() == 'PyPy' and\n                               sys.version_info > (3,) and\n                               sys.pypy_version_info < (5, 9),\n                               'pypy3 5.8 has buggy ssl module')\n\n\ndef refusing_port():\n    \"\"\"Returns a local port number that will refuse all connections.\n\n    Return value is (cleanup_func, port); the cleanup function\n    must be called to free the port to be reused.\n    \"\"\"\n    # On travis-ci, port numbers are reassigned frequently. To avoid\n    # collisions with other tests, we use an open client-side socket's\n    # ephemeral port number to ensure that nothing can listen on that\n    # port.\n    server_socket, port = bind_unused_port()\n    server_socket.setblocking(1)\n    client_socket = socket.socket()\n    client_socket.connect((\"127.0.0.1\", port))\n    conn, client_addr = server_socket.accept()\n    conn.close()\n    server_socket.close()\n    return (client_socket.close, client_addr[1])\n\n\ndef exec_test(caller_globals, caller_locals, s):\n    \"\"\"Execute ``s`` in a given context and return the result namespace.\n\n    Used to define functions for tests in particular python\n    versions that would be syntax errors in older versions.\n    \"\"\"\n    # Flatten the real global and local namespace into our fake\n    # globals: it's all global from the perspective of code defined\n    # in s.\n    global_namespace = dict(caller_globals, **caller_locals)  # type: ignore\n    local_namespace = {}\n    exec(textwrap.dedent(s), global_namespace, local_namespace)\n    return local_namespace\n\n\ndef is_coverage_running():\n    \"\"\"Return whether coverage is currently running.\n    \"\"\"\n    if 'coverage' not in sys.modules:\n        return False\n    tracer = sys.gettrace()\n    if tracer is None:\n        return False\n    try:\n        mod = tracer.__module__\n    except AttributeError:\n        try:\n            mod = tracer.__class__.__module__\n        except AttributeError:\n            return False\n    return mod.startswith('coverage')\n\n\ndef subTest(test, *args, **kwargs):\n    \"\"\"Compatibility shim for unittest.TestCase.subTest.\n\n    Usage: ``with tornado.test.util.subTest(self, x=x):``\n    \"\"\"\n    try:\n        subTest = test.subTest  # py34+\n    except AttributeError:\n        subTest = contextlib.contextmanager(lambda *a, **kw: (yield))\n    return subTest(*args, **kwargs)\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function\n\nimport contextlib\nimport os\nimport platform\nimport socket\nimport sys\nimport textwrap\n\nfrom tornado.testing import bind_unused_port\n\n# Delegate the choice of unittest or unittest2 to tornado.testing.\nfrom tornado.testing import unittest\n\nskipIfNonUnix = unittest.skipIf(os.name != 'posix' or sys.platform == 'cygwin',\n                                \"non-unix platform\")\n\n# travis-ci.org runs our tests in an overworked virtual machine, which makes\n# timing-related tests unreliable.\nskipOnTravis = unittest.skipIf('TRAVIS' in os.environ,\n                               'timing tests unreliable on travis')\n\nskipOnAppEngine = unittest.skipIf('APPENGINE_RUNTIME' in os.environ,\n                                  'not available on Google App Engine')\n\n# Set the environment variable NO_NETWORK=1 to disable any tests that\n# depend on an external network.\nskipIfNoNetwork = unittest.skipIf('NO_NETWORK' in os.environ,\n                                  'network access disabled')\n\nskipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 (yield from) not available')\nskipBefore35 = unittest.skipIf(sys.version_info < (3, 5), 'PEP 492 (async/await) not available')\nskipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',\n                                 'Not CPython implementation')\n\n# Used for tests affected by\n# https://bitbucket.org/pypy/pypy/issues/2616/incomplete-error-handling-in\n# TODO: remove this after pypy3 5.8 is obsolete.\nskipPypy3V58 = unittest.skipIf(platform.python_implementation() == 'PyPy' and\n                               sys.version_info > (3,) and\n                               sys.pypy_version_info < (5, 9),\n                               'pypy3 5.8 has buggy ssl module')\n\ndef _detect_ipv6():\n    if not socket.has_ipv6:\n        # socket.has_ipv6 check reports whether ipv6 was present at compile\n        # time. It's usually true even when ipv6 doesn't work for other reasons.\n        return False\n    sock = None\n    try:\n        sock = socket.socket(socket.AF_INET6)\n        sock.bind(('::1', 0))\n    except socket.error:\n        return False\n    finally:\n        if sock is not None:\n            sock.close()\n    return True\n\nskipIfNoIPv6 = unittest.skipIf(not _detect_ipv6(), 'ipv6 support not present')\n\n\ndef refusing_port():\n    \"\"\"Returns a local port number that will refuse all connections.\n\n    Return value is (cleanup_func, port); the cleanup function\n    must be called to free the port to be reused.\n    \"\"\"\n    # On travis-ci, port numbers are reassigned frequently. To avoid\n    # collisions with other tests, we use an open client-side socket's\n    # ephemeral port number to ensure that nothing can listen on that\n    # port.\n    server_socket, port = bind_unused_port()\n    server_socket.setblocking(1)\n    client_socket = socket.socket()\n    client_socket.connect((\"127.0.0.1\", port))\n    conn, client_addr = server_socket.accept()\n    conn.close()\n    server_socket.close()\n    return (client_socket.close, client_addr[1])\n\n\ndef exec_test(caller_globals, caller_locals, s):\n    \"\"\"Execute ``s`` in a given context and return the result namespace.\n\n    Used to define functions for tests in particular python\n    versions that would be syntax errors in older versions.\n    \"\"\"\n    # Flatten the real global and local namespace into our fake\n    # globals: it's all global from the perspective of code defined\n    # in s.\n    global_namespace = dict(caller_globals, **caller_locals)  # type: ignore\n    local_namespace = {}\n    exec(textwrap.dedent(s), global_namespace, local_namespace)\n    return local_namespace\n\n\ndef is_coverage_running():\n    \"\"\"Return whether coverage is currently running.\n    \"\"\"\n    if 'coverage' not in sys.modules:\n        return False\n    tracer = sys.gettrace()\n    if tracer is None:\n        return False\n    try:\n        mod = tracer.__module__\n    except AttributeError:\n        try:\n            mod = tracer.__class__.__module__\n        except AttributeError:\n            return False\n    return mod.startswith('coverage')\n\n\ndef subTest(test, *args, **kwargs):\n    \"\"\"Compatibility shim for unittest.TestCase.subTest.\n\n    Usage: ``with tornado.test.util.subTest(self, x=x):``\n    \"\"\"\n    try:\n        subTest = test.subTest  # py34+\n    except AttributeError:\n        subTest = contextlib.contextmanager(lambda *a, **kw: (yield))\n    return subTest(*args, **kwargs)\n",
            "header": {
                "file": {
                    "path": "tornado/test/util.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "0a9438ba",
                "new_commit_hash": "1d34ec08",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/util.py"
            },
            "plus_file": {
                "path": "b/tornado/test/util.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 28,
                            "length": 9
                        },
                        "new_range": {
                            "start": 28,
                            "length": 6
                        },
                        "section": "skipOnAppEngine = unittest.skipIf('APPENGINE_RUNTIME' in os.environ,"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "skipIfNoNetwork = unittest.skipIf('NO_NETWORK' in os.environ,",
                                "type": "context"
                            },
                            {
                                "content": "                                  'network access disabled')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "skipIfNoIPv6 = unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "skipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 (yield from) not available')",
                                "type": "context"
                            },
                            {
                                "content": "skipBefore35 = unittest.skipIf(sys.version_info < (3, 5), 'PEP 492 (async/await) not available')",
                                "type": "context"
                            },
                            {
                                "content": "skipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": [
                        {
                            "file_name": "tornado/test/util.py",
                            "type": "statement",
                            "name": "",
                            "content": "skipIfNoIPv6 = unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')",
                            "ast_type_str": "Assign",
                            "start_lineno": 31,
                            "end_lineno": 31,
                            "parent": null
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 44,
                            "length": 6
                        },
                        "new_range": {
                            "start": 41,
                            "length": 24
                        },
                        "section": "skipPypy3V58 = unittest.skipIf(platform.python_implementation() == 'PyPy' and"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                               sys.pypy_version_info < (5, 9),",
                                "type": "context"
                            },
                            {
                                "content": "                               'pypy3 5.8 has buggy ssl module')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def _detect_ipv6():",
                                "type": "added"
                            },
                            {
                                "content": "    if not socket.has_ipv6:",
                                "type": "added"
                            },
                            {
                                "content": "        # socket.has_ipv6 check reports whether ipv6 was present at compile",
                                "type": "added"
                            },
                            {
                                "content": "        # time. It's usually true even when ipv6 doesn't work for other reasons.",
                                "type": "added"
                            },
                            {
                                "content": "        return False",
                                "type": "added"
                            },
                            {
                                "content": "    sock = None",
                                "type": "added"
                            },
                            {
                                "content": "    try:",
                                "type": "added"
                            },
                            {
                                "content": "        sock = socket.socket(socket.AF_INET6)",
                                "type": "added"
                            },
                            {
                                "content": "        sock.bind(('::1', 0))",
                                "type": "added"
                            },
                            {
                                "content": "    except socket.error:",
                                "type": "added"
                            },
                            {
                                "content": "        return False",
                                "type": "added"
                            },
                            {
                                "content": "    finally:",
                                "type": "added"
                            },
                            {
                                "content": "        if sock is not None:",
                                "type": "added"
                            },
                            {
                                "content": "            sock.close()",
                                "type": "added"
                            },
                            {
                                "content": "    return True",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "skipIfNoIPv6 = unittest.skipIf(not _detect_ipv6(), 'ipv6 support not present')",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def refusing_port():",
                                "type": "context"
                            },
                            {
                                "content": "    \"\"\"Returns a local port number that will refuse all connections.",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/util.py",
                            "type": "function",
                            "name": "_detect_ipv6",
                            "content": "def _detect_ipv6():\n    if not socket.has_ipv6:\n        # socket.has_ipv6 check reports whether ipv6 was present at compile\n        # time. It's usually true even when ipv6 doesn't work for other reasons.\n        return False\n    sock = None\n    try:\n        sock = socket.socket(socket.AF_INET6)\n        sock.bind(('::1', 0))\n    except socket.error:\n        return False\n    finally:\n        if sock is not None:\n            sock.close()\n    return True",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 44,
                            "end_lineno": 58,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/util.py",
                            "type": "statement",
                            "name": "",
                            "content": "skipIfNoIPv6 = unittest.skipIf(not _detect_ipv6(), 'ipv6 support not present')",
                            "ast_type_str": "Assign",
                            "start_lineno": 60,
                            "end_lineno": 60,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function\nfrom tornado.concurrent import Future\nfrom tornado import gen\nfrom tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str, to_basestring\nfrom tornado.httputil import format_timestamp\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import IOStream\nfrom tornado import locale\nfrom tornado.log import app_log, gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.template import DictLoader\nfrom tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipBefore35, exec_test\nfrom tornado.util import ObjectDict, unicode_type, timedelta_to_seconds, PY3\nfrom tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish, removeslash, addslash, RedirectHandler as WebRedirectHandler, get_signature_key_version, GZipContentEncoding\n\nimport binascii\nimport contextlib\nimport copy\nimport datetime\nimport email.utils\nimport gzip\nfrom io import BytesIO\nimport itertools\nimport logging\nimport os\nimport re\nimport socket\n\nif PY3:\n    import urllib.parse as urllib_parse  # py3\nelse:\n    import urllib as urllib_parse  # py2\n\nwsgi_safe_tests = []\n\n\ndef relpath(*a):\n    return os.path.join(os.path.dirname(__file__), *a)\n\n\ndef wsgi_safe(cls):\n    wsgi_safe_tests.append(cls)\n    return cls\n\n\nclass WebTestCase(AsyncHTTPTestCase):\n    \"\"\"Base class for web tests that also supports WSGI mode.\n\n    Override get_handlers and get_app_kwargs instead of get_app.\n    Append to wsgi_safe to have it run in wsgi_test as well.\n    \"\"\"\n    def get_app(self):\n        self.app = Application(self.get_handlers(), **self.get_app_kwargs())\n        return self.app\n\n    def get_handlers(self):\n        raise NotImplementedError()\n\n    def get_app_kwargs(self):\n        return {}\n\n\nclass SimpleHandlerTestCase(WebTestCase):\n    \"\"\"Simplified base class for tests that work with a single handler class.\n\n    To use, define a nested class named ``Handler``.\n    \"\"\"\n    def get_handlers(self):\n        return [('/', self.Handler)]\n\n\nclass HelloHandler(RequestHandler):\n    def get(self):\n        self.write('hello')\n\n\nclass CookieTestRequestHandler(RequestHandler):\n    # stub out enough methods to make the secure_cookie functions work\n    def __init__(self, cookie_secret='0123456789', key_version=None):\n        # don't call super.__init__\n        self._cookies = {}\n        if key_version is None:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret))\n        else:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret,\n                                                        key_version=key_version))\n\n    def get_cookie(self, name):\n        return self._cookies.get(name)\n\n    def set_cookie(self, name, value, expires_days=None):\n        self._cookies[name] = value\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV1Test(unittest.TestCase):\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1),\n                         b'bar')\n\n    def test_cookie_tampering_future_timestamp(self):\n        handler = CookieTestRequestHandler()\n        # this string base64-encodes to '12345678'\n        handler.set_secure_cookie('foo', binascii.a2b_hex(b'd76df8e7aefc'),\n                                  version=1)\n        cookie = handler._cookies['foo']\n        match = re.match(br'12345678\\|([0-9]+)\\|([0-9a-f]+)', cookie)\n        self.assertTrue(match)\n        timestamp = match.group(1)\n        sig = match.group(2)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '12345678', timestamp),\n            sig)\n        # shifting digits from payload to timestamp doesn't alter signature\n        # (this is not desirable behavior, just confirming that that's how it\n        # works)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '1234', b'5678' + timestamp),\n            sig)\n        # tamper with the cookie\n        handler._cookies['foo'] = utf8('1234|5678%s|%s' % (\n            to_basestring(timestamp), to_basestring(sig)))\n        # it gets rejected\n        with ExpectLog(gen_log, \"Cookie timestamp in future\"):\n            self.assertTrue(\n                handler.get_secure_cookie('foo', min_version=1) is None)\n\n    def test_arbitrary_bytes(self):\n        # Secure cookies accept arbitrary data (which is base64 encoded).\n        # Note that normal cookies accept only a subset of ascii.\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'\\xe9', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1), b'\\xe9')\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV2Test(unittest.TestCase):\n    KEY_VERSIONS = {\n        0: 'ajklasdf0ojaisdf',\n        1: 'aslkjasaolwkjsdf'\n    }\n\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=2)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=2), b'bar')\n\n    def test_key_version_roundtrip(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_roundtrip_differing_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=1)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_increment_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_invalidate_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_key_versions = self.KEY_VERSIONS.copy()\n        new_key_versions.pop(0)\n        new_handler = CookieTestRequestHandler(cookie_secret=new_key_versions,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), None)\n\n\nclass CookieTest(WebTestCase):\n    def get_handlers(self):\n        class SetCookieHandler(RequestHandler):\n            def get(self):\n                # Try setting cookies with different argument types\n                # to ensure that everything gets encoded correctly\n                self.set_cookie(\"str\", \"asdf\")\n                self.set_cookie(\"unicode\", u\"qwer\")\n                self.set_cookie(\"bytes\", b\"zxcv\")\n\n        class GetCookieHandler(RequestHandler):\n            def get(self):\n                self.write(self.get_cookie(\"foo\", \"default\"))\n\n        class SetCookieDomainHandler(RequestHandler):\n            def get(self):\n                # unicode domain and path arguments shouldn't break things\n                # either (see bug #285)\n                self.set_cookie(\"unicode_args\", \"blah\", domain=u\"foo.com\",\n                                path=u\"/foo\")\n\n        class SetCookieSpecialCharHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"equals\", \"a=b\")\n                self.set_cookie(\"semicolon\", \"a;b\")\n                self.set_cookie(\"quote\", 'a\"b')\n\n        class SetCookieOverwriteHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"b\", domain=\"example.com\")\n                self.set_cookie(\"c\", \"d\", domain=\"example.com\")\n                # A second call with the same name clobbers the first.\n                # Attributes from the first call are not carried over.\n                self.set_cookie(\"a\", \"e\")\n\n        class SetCookieMaxAgeHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", max_age=10)\n\n        class SetCookieExpiresDaysHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", expires_days=10)\n\n        class SetCookieFalsyFlags(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"1\", secure=True)\n                self.set_cookie(\"b\", \"1\", secure=False)\n                self.set_cookie(\"c\", \"1\", httponly=True)\n                self.set_cookie(\"d\", \"1\", httponly=False)\n\n        return [(\"/set\", SetCookieHandler),\n                (\"/get\", GetCookieHandler),\n                (\"/set_domain\", SetCookieDomainHandler),\n                (\"/special_char\", SetCookieSpecialCharHandler),\n                (\"/set_overwrite\", SetCookieOverwriteHandler),\n                (\"/set_max_age\", SetCookieMaxAgeHandler),\n                (\"/set_expires_days\", SetCookieExpiresDaysHandler),\n                (\"/set_falsy_flags\", SetCookieFalsyFlags)\n                ]\n\n    def test_set_cookie(self):\n        response = self.fetch(\"/set\")\n        self.assertEqual(sorted(response.headers.get_list(\"Set-Cookie\")),\n                         [\"bytes=zxcv; Path=/\",\n                          \"str=asdf; Path=/\",\n                          \"unicode=qwer; Path=/\",\n                          ])\n\n    def test_get_cookie(self):\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"foo=bar\"})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": 'foo=\"bar\"'})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"/=exception;\"})\n        self.assertEqual(response.body, b\"default\")\n\n    def test_set_cookie_domain(self):\n        response = self.fetch(\"/set_domain\")\n        self.assertEqual(response.headers.get_list(\"Set-Cookie\"),\n                         [\"unicode_args=blah; Domain=foo.com; Path=/foo\"])\n\n    def test_cookie_special_char(self):\n        response = self.fetch(\"/special_char\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        self.assertEqual(len(headers), 3)\n        self.assertEqual(headers[0], 'equals=\"a=b\"; Path=/')\n        self.assertEqual(headers[1], 'quote=\"a\\\\\"b\"; Path=/')\n        # python 2.7 octal-escapes the semicolon; older versions leave it alone\n        self.assertTrue(headers[2] in ('semicolon=\"a;b\"; Path=/',\n                                       'semicolon=\"a\\\\073b\"; Path=/'),\n                        headers[2])\n\n        data = [('foo=a=b', 'a=b'),\n                ('foo=\"a=b\"', 'a=b'),\n                ('foo=\"a;b\"', '\"a'),  # even quoted, \";\" is a delimiter\n                ('foo=a\\\\073b', 'a\\\\073b'),  # escapes only decoded in quotes\n                ('foo=\"a\\\\073b\"', 'a;b'),\n                ('foo=\"a\\\\\"b\"', 'a\"b'),\n                ]\n        for header, expected in data:\n            logging.debug(\"trying %r\", header)\n            response = self.fetch(\"/get\", headers={\"Cookie\": header})\n            self.assertEqual(response.body, utf8(expected))\n\n    def test_set_cookie_overwrite(self):\n        response = self.fetch(\"/set_overwrite\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"a=e; Path=/\", \"c=d; Domain=example.com; Path=/\"])\n\n    def test_set_cookie_max_age(self):\n        response = self.fetch(\"/set_max_age\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"foo=bar; Max-Age=10; Path=/\"])\n\n    def test_set_cookie_expires_days(self):\n        response = self.fetch(\"/set_expires_days\")\n        header = response.headers.get(\"Set-Cookie\")\n        match = re.match(\"foo=bar; expires=(?P<expires>.+); Path=/\", header)\n        self.assertIsNotNone(match)\n\n        expires = datetime.datetime.utcnow() + datetime.timedelta(days=10)\n        header_expires = datetime.datetime(\n            *email.utils.parsedate(match.groupdict()[\"expires\"])[:6])\n        self.assertTrue(abs(timedelta_to_seconds(expires - header_expires)) < 10)\n\n    def test_set_cookie_false_flags(self):\n        response = self.fetch(\"/set_falsy_flags\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        # The secure and httponly headers are capitalized in py35 and\n        # lowercase in older versions.\n        self.assertEqual(headers[0].lower(), 'a=1; path=/; secure')\n        self.assertEqual(headers[1].lower(), 'b=1; path=/')\n        self.assertEqual(headers[2].lower(), 'c=1; httponly; path=/')\n        self.assertEqual(headers[3].lower(), 'd=1; path=/')\n\n\nclass AuthRedirectRequestHandler(RequestHandler):\n    def initialize(self, login_url):\n        self.login_url = login_url\n\n    def get_login_url(self):\n        return self.login_url\n\n    @authenticated\n    def get(self):\n        # we'll never actually get here because the test doesn't follow redirects\n        self.send_error(500)\n\n\nclass AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])\n\n\nclass ConnectionCloseHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n\n    @asynchronous\n    def get(self):\n        self.test.on_handler_waiting()\n\n    def on_connection_close(self):\n        self.test.on_connection_close()\n\n\nclass ConnectionCloseTest(WebTestCase):\n    def get_handlers(self):\n        return [('/', ConnectionCloseHandler, dict(test=self))]\n\n    def test_connection_close(self):\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        self.stream = IOStream(s)\n        self.stream.write(b\"GET / HTTP/1.0\\r\\n\\r\\n\")\n        self.wait()\n\n    def on_handler_waiting(self):\n        logging.debug('handler waiting')\n        self.stream.close()\n\n    def on_connection_close(self):\n        logging.debug('connection closed')\n        self.stop()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self, *path_args):\n        # Type checks: web.py interfaces convert argument values to\n        # unicode strings (by default, but see also decode_argument).\n        # In httpserver.py (i.e. self.request.arguments), they're left\n        # as bytes.  Keys are always native strings.\n        for key in self.request.arguments:\n            if type(key) != str:\n                raise Exception(\"incorrect type for key: %r\" % type(key))\n            for value in self.request.arguments[key]:\n                if type(value) != bytes:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n            for value in self.get_arguments(key):\n                if type(value) != unicode_type:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n        for arg in path_args:\n            if type(arg) != unicode_type:\n                raise Exception(\"incorrect type for path arg: %r\" % type(arg))\n        self.write(dict(path=self.request.path,\n                        path_args=path_args,\n                        args=recursive_unicode(self.request.arguments)))\n\n\nclass RequestEncodingTest(WebTestCase):\n    def get_handlers(self):\n        return [(\"/group/(.*)\", EchoHandler),\n                (\"/slashes/([^/]*)/([^/]*)\", EchoHandler),\n                ]\n\n    def fetch_json(self, path):\n        return json_decode(self.fetch(path).body)\n\n    def test_group_question_mark(self):\n        # Ensure that url-encoded question marks are handled properly\n        self.assertEqual(self.fetch_json('/group/%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={}))\n        self.assertEqual(self.fetch_json('/group/%3F?%3F=%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={'?': ['?']}))\n\n    def test_group_encoding(self):\n        # Path components and query arguments should be decoded the same way\n        self.assertEqual(self.fetch_json('/group/%C3%A9?arg=%C3%A9'),\n                         {u\"path\": u\"/group/%C3%A9\",\n                          u\"path_args\": [u\"\\u00e9\"],\n                          u\"args\": {u\"arg\": [u\"\\u00e9\"]}})\n\n    def test_slashes(self):\n        # Slashes may be escaped to appear as a single \"directory\" in the path,\n        # but they are then unescaped when passed to the get() method.\n        self.assertEqual(self.fetch_json('/slashes/foo/bar'),\n                         dict(path=\"/slashes/foo/bar\",\n                              path_args=[\"foo\", \"bar\"],\n                              args={}))\n        self.assertEqual(self.fetch_json('/slashes/a%2Fb/c%2Fd'),\n                         dict(path=\"/slashes/a%2Fb/c%2Fd\",\n                              path_args=[\"a/b\", \"c/d\"],\n                              args={}))\n\n    def test_error(self):\n        # Percent signs (encoded as %25) should not mess up printf-style\n        # messages in logs\n        with ExpectLog(gen_log, \".*Invalid unicode\"):\n            self.fetch(\"/group/?arg=%25%e9\")\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n\n        self.check_type('status', self.get_status(), int)\n\n        # get_argument is an exception from the general rule of using\n        # type str for non-body data mainly for historical reasons.\n        self.check_type('argument', self.get_argument('foo'), unicode_type)\n        self.check_type('cookie_key', list(self.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.cookies.values())[0].value, str)\n\n        # Secure cookies return bytes because they can contain arbitrary\n        # data, but regular cookies are native strings.\n        if list(self.cookies.keys()) != ['asdf']:\n            raise Exception(\"unexpected values for cookie keys: %r\" %\n                            self.cookies.keys())\n        self.check_type('get_secure_cookie', self.get_secure_cookie('asdf'), bytes)\n        self.check_type('get_cookie', self.get_cookie('asdf'), str)\n\n        self.check_type('xsrf_token', self.xsrf_token, bytes)\n        self.check_type('xsrf_form_html', self.xsrf_form_html(), str)\n\n        self.check_type('reverse_url', self.reverse_url('typecheck', 'foo'), str)\n\n        self.check_type('request_summary', self._request_summary(), str)\n\n    def get(self, path_component):\n        # path_component uses type unicode instead of str for consistency\n        # with get_argument()\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def post(self, path_component):\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass DecodeArgHandler(RequestHandler):\n    def decode_argument(self, value, name=None):\n        if type(value) != bytes:\n            raise Exception(\"unexpected type for value: %r\" % type(value))\n        # use self.request.arguments directly to avoid recursion\n        if 'encoding' in self.request.arguments:\n            return value.decode(to_unicode(self.request.arguments['encoding'][0]))\n        else:\n            return value\n\n    def get(self, arg):\n        def describe(s):\n            if type(s) == bytes:\n                return [\"bytes\", native_str(binascii.b2a_hex(s))]\n            elif type(s) == unicode_type:\n                return [\"unicode\", s]\n            raise Exception(\"unknown type\")\n        self.write({'path': describe(arg),\n                    'query': describe(self.get_argument(\"foo\")),\n                    })\n\n\nclass LinkifyHandler(RequestHandler):\n    def get(self):\n        self.render(\"linkify.html\", message=\"http://example.com\")\n\n\nclass UIModuleResourceHandler(RequestHandler):\n    def get(self):\n        self.render(\"page.html\", entries=[1, 2])\n\n\nclass OptionalPathHandler(RequestHandler):\n    def get(self, path):\n        self.write({\"path\": path})\n\n\nclass FlowControlHandler(RequestHandler):\n    # These writes are too small to demonstrate real flow control,\n    # but at least it shows that the callbacks get run.\n    @asynchronous\n    def get(self):\n        self.write(\"1\")\n        self.flush(callback=self.step2)\n\n    def step2(self):\n        self.write(\"2\")\n        self.flush(callback=self.step3)\n\n    def step3(self):\n        self.write(\"3\")\n        self.finish()\n\n\nclass MultiHeaderHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"x-overwrite\", \"1\")\n        self.set_header(\"X-Overwrite\", 2)\n        self.add_header(\"x-multi\", 3)\n        self.add_header(\"X-Multi\", \"4\")\n\n\nclass RedirectHandler(RequestHandler):\n    def get(self):\n        if self.get_argument('permanent', None) is not None:\n            self.redirect('/', permanent=int(self.get_argument('permanent')))\n        elif self.get_argument('status', None) is not None:\n            self.redirect('/', status=int(self.get_argument('status')))\n        else:\n            raise Exception(\"didn't get permanent or status arguments\")\n\n\nclass EmptyFlushCallbackHandler(RequestHandler):\n    @asynchronous\n    @gen.engine\n    def get(self):\n        # Ensure that the flush callback is run whether or not there\n        # was any output.  The gen.Task and direct yield forms are\n        # equivalent.\n        yield gen.Task(self.flush)  # \"empty\" flush, but writes headers\n        yield gen.Task(self.flush)  # empty flush\n        self.write(\"o\")\n        yield self.flush()  # flushes the \"o\"\n        yield self.flush()  # empty flush\n        self.finish(\"k\")\n\n\nclass HeaderInjectionHandler(RequestHandler):\n    def get(self):\n        try:\n            self.set_header(\"X-Foo\", \"foo\\r\\nX-Bar: baz\")\n            raise Exception(\"Didn't get expected exception\")\n        except ValueError as e:\n            if \"Unsafe header value\" in str(e):\n                self.finish(b\"ok\")\n            else:\n                raise\n\n\nclass GetArgumentHandler(RequestHandler):\n    def prepare(self):\n        if self.get_argument('source', None) == 'query':\n            method = self.get_query_argument\n        elif self.get_argument('source', None) == 'body':\n            method = self.get_body_argument\n        else:\n            method = self.get_argument\n        self.finish(method(\"foo\", \"default\"))\n\n\nclass GetArgumentsHandler(RequestHandler):\n    def prepare(self):\n        self.finish(dict(default=self.get_arguments(\"foo\"),\n                         query=self.get_query_arguments(\"foo\"),\n                         body=self.get_body_arguments(\"foo\")))\n\n\n# This test is shared with wsgi_test.py\n@wsgi_safe\nclass WSGISafeWebTest(WebTestCase):\n    COOKIE_SECRET = \"WebTest.COOKIE_SECRET\"\n\n    def get_app_kwargs(self):\n        loader = DictLoader({\n            \"linkify.html\": \"{% module linkify(message) %}\",\n            \"page.html\": \"\"\"\\\n<html><head></head><body>\n{% for e in entries %}\n{% module Template(\"entry.html\", entry=e) %}\n{% end %}\n</body></html>\"\"\",\n            \"entry.html\": \"\"\"\\\n{{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\", embedded_javascript=\"js_embed()\", css_files=[\"/base.css\", \"/foo.css\"], javascript_files=\"/common.js\", html_head=\"<meta>\", html_body='<script src=\"/analytics.js\"/>') }}\n<div class=\"entry\">...</div>\"\"\",\n        })\n        return dict(template_loader=loader,\n                    autoescape=\"xhtml_escape\",\n                    cookie_secret=self.COOKIE_SECRET)\n\n    def tearDown(self):\n        super(WSGISafeWebTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        urls = [\n            url(\"/typecheck/(.*)\", TypeCheckHandler, name='typecheck'),\n            url(\"/decode_arg/(.*)\", DecodeArgHandler, name='decode_arg'),\n            url(\"/decode_arg_kw/(?P<arg>.*)\", DecodeArgHandler),\n            url(\"/linkify\", LinkifyHandler),\n            url(\"/uimodule_resources\", UIModuleResourceHandler),\n            url(\"/optional_path/(.+)?\", OptionalPathHandler),\n            url(\"/multi_header\", MultiHeaderHandler),\n            url(\"/redirect\", RedirectHandler),\n            url(\"/web_redirect_permanent\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\"}),\n            url(\"/web_redirect\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\", \"permanent\": False}),\n            url(\"//web_redirect_double_slash\", WebRedirectHandler, {\"url\": '/web_redirect_newpath'}),\n            url(\"/header_injection\", HeaderInjectionHandler),\n            url(\"/get_argument\", GetArgumentHandler),\n            url(\"/get_arguments\", GetArgumentsHandler),\n        ]\n        return urls\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n    def test_types(self):\n        cookie_value = to_unicode(create_signed_value(self.COOKIE_SECRET,\n                                                      \"asdf\", \"qwer\"))\n        response = self.fetch(\"/typecheck/asdf?foo=bar\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value})\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck/asdf?foo=bar\", method=\"POST\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value},\n                              body=\"foo=bar\")\n\n    def test_decode_argument(self):\n        # These urls all decode to the same thing\n        urls = [\"/decode_arg/%C3%A9?foo=%C3%A9&encoding=utf-8\",\n                \"/decode_arg/%E9?foo=%E9&encoding=latin1\",\n                \"/decode_arg_kw/%E9?foo=%E9&encoding=latin1\",\n                ]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'\\u00e9'],\n                                    u'query': [u'unicode', u'\\u00e9'],\n                                    })\n\n        response = self.fetch(\"/decode_arg/%C3%A9?foo=%C3%A9\")\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {u'path': [u'bytes', u'c3a9'],\n                                u'query': [u'bytes', u'c3a9'],\n                                })\n\n    def test_decode_argument_invalid_unicode(self):\n        # test that invalid unicode in URLs causes 400, not 500\n        with ExpectLog(gen_log, \".*Invalid unicode.*\"):\n            response = self.fetch(\"/typecheck/invalid%FF\")\n            self.assertEqual(response.code, 400)\n            response = self.fetch(\"/typecheck/invalid?foo=%FF\")\n            self.assertEqual(response.code, 400)\n\n    def test_decode_argument_plus(self):\n        # These urls are all equivalent.\n        urls = [\"/decode_arg/1%20%2B%201?foo=1%20%2B%201&encoding=utf-8\",\n                \"/decode_arg/1%20+%201?foo=1+%2B+1&encoding=utf-8\"]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'1 + 1'],\n                                    u'query': [u'unicode', u'1 + 1'],\n                                    })\n\n    def test_reverse_url(self):\n        self.assertEqual(self.app.reverse_url('decode_arg', 'foo'),\n                         '/decode_arg/foo')\n        self.assertEqual(self.app.reverse_url('decode_arg', 42),\n                         '/decode_arg/42')\n        self.assertEqual(self.app.reverse_url('decode_arg', b'\\xe9'),\n                         '/decode_arg/%E9')\n        self.assertEqual(self.app.reverse_url('decode_arg', u'\\u00e9'),\n                         '/decode_arg/%C3%A9')\n        self.assertEqual(self.app.reverse_url('decode_arg', '1 + 1'),\n                         '/decode_arg/1%20%2B%201')\n\n    def test_uimodule_unescaped(self):\n        response = self.fetch(\"/linkify\")\n        self.assertEqual(response.body,\n                         b\"<a href=\\\"http://example.com\\\">http://example.com</a>\")\n\n    def test_uimodule_resources(self):\n        response = self.fetch(\"/uimodule_resources\")\n        self.assertEqual(response.body, b\"\"\"\\\n<html><head><link href=\"/base.css\" type=\"text/css\" rel=\"stylesheet\"/><link href=\"/foo.css\" type=\"text/css\" rel=\"stylesheet\"/>\n<style type=\"text/css\">\n.entry { margin-bottom: 1em; }\n</style>\n<meta>\n</head><body>\n\n\n<div class=\"entry\">...</div>\n\n\n<div class=\"entry\">...</div>\n\n<script src=\"/common.js\" type=\"text/javascript\"></script>\n<script type=\"text/javascript\">\n//<![CDATA[\njs_embed()\n//]]>\n</script>\n<script src=\"/analytics.js\"/>\n</body></html>\"\"\")\n\n    def test_optional_path(self):\n        self.assertEqual(self.fetch_json(\"/optional_path/foo\"),\n                         {u\"path\": u\"foo\"})\n        self.assertEqual(self.fetch_json(\"/optional_path/\"),\n                         {u\"path\": None})\n\n    def test_multi_header(self):\n        response = self.fetch(\"/multi_header\")\n        self.assertEqual(response.headers[\"x-overwrite\"], \"2\")\n        self.assertEqual(response.headers.get_list(\"x-multi\"), [\"3\", \"4\"])\n\n    def test_redirect(self):\n        response = self.fetch(\"/redirect?permanent=1\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        response = self.fetch(\"/redirect?permanent=0\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        response = self.fetch(\"/redirect?status=307\", follow_redirects=False)\n        self.assertEqual(response.code, 307)\n\n    def test_web_redirect(self):\n        response = self.fetch(\"/web_redirect_permanent\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n        response = self.fetch(\"/web_redirect\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_web_redirect_double_slash(self):\n        response = self.fetch(\"//web_redirect_double_slash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_header_injection(self):\n        response = self.fetch(\"/header_injection\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_get_argument(self):\n        response = self.fetch(\"/get_argument?foo=bar\")\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?foo=\")\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument\")\n        self.assertEqual(response.body, b\"default\")\n\n        # Test merging of query and body arguments.\n        # In singular form, body arguments take precedence over query arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?foo=bar\", method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"hello\")\n        # In plural methods they are merged.\n        response = self.fetch(\"/get_arguments?foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(json_decode(response.body),\n                         dict(default=['bar', 'hello'],\n                              query=['bar'],\n                              body=['hello']))\n\n    def test_get_query_arguments(self):\n        # send as a post so we can ensure the separation between query\n        # string and body arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?source=query&foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?source=query&foo=\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument?source=query\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_get_body_arguments(self):\n        body = urllib_parse.urlencode(dict(foo=\"bar\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n\n        body = urllib_parse.urlencode(dict(foo=\"\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n\n        body = urllib_parse.urlencode(dict())\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_no_gzip(self):\n        response = self.fetch('/get_argument')\n        self.assertNotIn('Accept-Encoding', response.headers.get('Vary', ''))\n        self.assertNotIn('gzip', response.headers.get('Content-Encoding', ''))\n\n\nclass NonWSGIWebTests(WebTestCase):\n    def get_handlers(self):\n        return [(\"/flow_control\", FlowControlHandler),\n                (\"/empty_flush\", EmptyFlushCallbackHandler),\n                ]\n\n    def test_flow_control(self):\n        self.assertEqual(self.fetch(\"/flow_control\").body, b\"123\")\n\n    def test_empty_flush(self):\n        response = self.fetch(\"/empty_flush\")\n        self.assertEqual(response.body, b\"ok\")\n\n\n@wsgi_safe\nclass ErrorResponseTest(WebTestCase):\n    def get_handlers(self):\n        class DefaultHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    raise HTTPError(int(self.get_argument(\"status\")))\n                1 / 0\n\n        class WriteErrorHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    self.send_error(int(self.get_argument(\"status\")))\n                else:\n                    1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                self.set_header(\"Content-Type\", \"text/plain\")\n                if \"exc_info\" in kwargs:\n                    self.write(\"Exception: %s\" % kwargs[\"exc_info\"][0].__name__)\n                else:\n                    self.write(\"Status: %d\" % status_code)\n\n        class FailedWriteErrorHandler(RequestHandler):\n            def get(self):\n                1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                raise Exception(\"exception in write_error\")\n\n        return [url(\"/default\", DefaultHandler),\n                url(\"/write_error\", WriteErrorHandler),\n                url(\"/failed_write_error\", FailedWriteErrorHandler),\n                ]\n\n    def test_default(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/default\")\n            self.assertEqual(response.code, 500)\n            self.assertTrue(b\"500: Internal Server Error\" in response.body)\n\n            response = self.fetch(\"/default?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertTrue(b\"503: Service Unavailable\" in response.body)\n\n            response = self.fetch(\"/default?status=435\")\n            self.assertEqual(response.code, 435)\n            self.assertTrue(b\"435: Unknown\" in response.body)\n\n    def test_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"Exception: ZeroDivisionError\", response.body)\n\n            response = self.fetch(\"/write_error?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertEqual(b\"Status: 503\", response.body)\n\n    def test_failed_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/failed_write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"\", response.body)\n\n\n@wsgi_safe\nclass StaticFileTest(WebTestCase):\n    # The expected MD5 hash of robots.txt, used in tests that call\n    # StaticFileHandler.get_version\n    robots_txt_hash = b\"f71d20196d4caf35b6a670db8c70b03d\"\n    static_dir = os.path.join(os.path.dirname(__file__), 'static')\n\n    def get_handlers(self):\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                with_v = int(self.get_argument('include_version', 1))\n                self.write(self.static_url(path, include_version=with_v))\n\n        class AbsoluteStaticUrlHandler(StaticUrlHandler):\n            include_host = True\n\n        class OverrideStaticUrlHandler(RequestHandler):\n            def get(self, path):\n                do_include = bool(self.get_argument(\"include_host\"))\n                self.include_host = not do_include\n\n                regular_url = self.static_url(path)\n                override_url = self.static_url(path, include_host=do_include)\n                if override_url == regular_url:\n                    return self.write(str(False))\n\n                protocol = self.request.protocol + \"://\"\n                protocol_length = len(protocol)\n                check_regular = regular_url.find(protocol, 0, protocol_length)\n                check_override = override_url.find(protocol, 0, protocol_length)\n\n                if do_include:\n                    result = (check_override == 0 and check_regular == -1)\n                else:\n                    result = (check_override == -1 and check_regular == 0)\n                self.write(str(result))\n\n        return [('/static_url/(.*)', StaticUrlHandler),\n                ('/abs_static_url/(.*)', AbsoluteStaticUrlHandler),\n                ('/override_static_url/(.*)', OverrideStaticUrlHandler),\n                ('/root_static/(.*)', StaticFileHandler, dict(path='/'))]\n\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'))\n\n    def test_static_files(self):\n        response = self.fetch('/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n\n        response = self.fetch('/static/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n        self.assertEqual(response.headers.get(\"Content-Type\"), \"text/plain\")\n\n    def test_static_compressed_files(self):\n        response = self.fetch(\"/static/sample.xml.gz\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/gzip\")\n        response = self.fetch(\"/static/sample.xml.bz2\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/octet-stream\")\n        # make sure the uncompressed file still has the correct type\n        response = self.fetch(\"/static/sample.xml\")\n        self.assertTrue(response.headers.get(\"Content-Type\")\n                        in set((\"text/xml\", \"application/xml\")))\n\n    def test_static_url(self):\n        response = self.fetch(\"/static_url/robots.txt\")\n        self.assertEqual(response.body,\n                         b\"/static/robots.txt?v=\" + self.robots_txt_hash)\n\n    def test_absolute_static_url(self):\n        response = self.fetch(\"/abs_static_url/robots.txt\")\n        self.assertEqual(response.body, (\n            utf8(self.get_url(\"/\")) +\n            b\"static/robots.txt?v=\" +\n            self.robots_txt_hash\n        ))\n\n    def test_relative_version_exclusion(self):\n        response = self.fetch(\"/static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body, b\"/static/robots.txt\")\n\n    def test_absolute_version_exclusion(self):\n        response = self.fetch(\"/abs_static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body,\n                         utf8(self.get_url(\"/\") + \"static/robots.txt\"))\n\n    def test_include_host_override(self):\n        self._trigger_include_host_check(False)\n        self._trigger_include_host_check(True)\n\n    def _trigger_include_host_check(self, include_host):\n        path = \"/override_static_url/robots.txt?include_host=%s\"\n        response = self.fetch(path % int(include_host))\n        self.assertEqual(response.body, utf8(str(True)))\n\n    def get_and_head(self, *args, **kwargs):\n        \"\"\"Performs a GET and HEAD request and returns the GET response.\n\n        Fails if any ``Content-*`` headers returned by the two requests\n        differ.\n        \"\"\"\n        head_response = self.fetch(*args, method=\"HEAD\", **kwargs)\n        get_response = self.fetch(*args, method=\"GET\", **kwargs)\n        content_headers = set()\n        for h in itertools.chain(head_response.headers, get_response.headers):\n            if h.startswith('Content-'):\n                content_headers.add(h)\n        for h in content_headers:\n            self.assertEqual(head_response.headers.get(h),\n                             get_response.headers.get(h),\n                             \"%s differs between GET (%s) and HEAD (%s)\" %\n                             (h, head_response.headers.get(h),\n                              get_response.headers.get(h)))\n        return get_response\n\n    def test_static_304_if_modified_since(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': response1.headers['Last-Modified']})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue('Content-Length' not in response2.headers)\n        self.assertTrue('Last-Modified' not in response2.headers)\n\n    def test_static_304_if_none_match(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-None-Match': response1.headers['Etag']})\n        self.assertEqual(response2.code, 304)\n\n    def test_static_if_modified_since_pre_epoch(self):\n        # On windows, the functions that work with time_t do not accept\n        # negative values, and at least one client (processing.js) seems\n        # to use if-modified-since 1/1/1960 as a cache-busting technique.\n        response = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': 'Fri, 01 Jan 1960 00:00:00 GMT'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_if_modified_since_time_zone(self):\n        # Instead of the value from Last-Modified, make requests with times\n        # chosen just before and after the known modification time\n        # of the file to ensure that the right time zone is being used\n        # when parsing If-Modified-Since.\n        stat = os.stat(relpath('static/robots.txt'))\n\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime - 1)})\n        self.assertEqual(response.code, 200)\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime + 1)})\n        self.assertEqual(response.code, 304)\n\n    def test_static_etag(self):\n        response = self.get_and_head('/static/robots.txt')\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_with_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-9'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b\"User-agent\")\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"10\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 0-9/26\")\n\n    def test_static_with_range_full_file(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-'})\n        # Note: Chrome refuses to play audio if it gets an HTTP 206 in response\n        # to ``Range: bytes=0-`` :(\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_full_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-10000000'})\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_partial_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-10000000'})\n        self.assertEqual(response.code, 206)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()[1:]))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"25\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), \"bytes 1-25/26\")\n\n    def test_static_with_range_end_edge(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=22-'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_with_range_neg_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-4'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_invalid_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'asdf'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_unsatisfiable_range_zero_suffix(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-0'})\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n        self.assertEqual(response.code, 416)\n\n    def test_static_unsatisfiable_range_invalid_start(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=26'})\n        self.assertEqual(response.code, 416)\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n\n    def test_static_head(self):\n        response = self.fetch('/static/robots.txt', method='HEAD')\n        self.assertEqual(response.code, 200)\n        # No body was returned, but we did get the right content length.\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '26')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_head_range(self):\n        response = self.fetch('/static/robots.txt', method='HEAD',\n                              headers={'Range': 'bytes=1-4'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '4')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_range_if_none_match(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-4',\n            'If-None-Match': b'\"' + self.robots_txt_hash + b'\"'})\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.body, b'')\n        self.assertTrue('Content-Length' not in response.headers)\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_404(self):\n        response = self.get_and_head('/static/blarg')\n        self.assertEqual(response.code, 404)\n\n    def test_path_traversal_protection(self):\n        # curl_httpclient processes \"..\" on the client side, so we\n        # must test this with simple_httpclient.\n        self.http_client.close()\n        self.http_client = SimpleAsyncHTTPClient()\n        with ExpectLog(gen_log, \".*not in root static directory\"):\n            response = self.get_and_head('/static/../static_foo.txt')\n        # Attempted path traversal should result in 403, not 200\n        # (which means the check failed and the file was served)\n        # or 404 (which means that the file didn't exist and\n        # is probably a packaging error).\n        self.assertEqual(response.code, 403)\n\n    @unittest.skipIf(os.name != 'posix', 'non-posix OS')\n    def test_root_static_path(self):\n        # Sometimes people set the StaticFileHandler's path to '/'\n        # to disable Tornado's path validation (in conjunction with\n        # their own validation in get_absolute_path). Make sure\n        # that the stricter validation in 4.2.1 doesn't break them.\n        path = os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                            'static/robots.txt')\n        response = self.get_and_head('/root_static' + urllib_parse.quote(path))\n        self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass StaticDefaultFilenameTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return []\n\n    def test_static_default_filename(self):\n        response = self.fetch('/static/dir/', follow_redirects=False)\n        self.assertEqual(response.code, 200)\n        self.assertEqual(b'this is the index\\n', response.body)\n\n    def test_static_default_redirect(self):\n        response = self.fetch('/static/dir', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertTrue(response.headers['Location'].endswith('/static/dir/'))\n\n\n@wsgi_safe\nclass StaticFileWithPathTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return [(\"/foo/(.*)\", StaticFileHandler, {\n            \"path\": relpath(\"templates/\"),\n        })]\n\n    def test_serve(self):\n        response = self.fetch(\"/foo/utf8.html\")\n        self.assertEqual(response.body, b\"H\\xc3\\xa9llo\\n\")\n\n\n@wsgi_safe\nclass CustomStaticFileTest(WebTestCase):\n    def get_handlers(self):\n        class MyStaticFileHandler(StaticFileHandler):\n            @classmethod\n            def make_static_url(cls, settings, path):\n                version_hash = cls.get_version(settings, path)\n                extension_index = path.rindex('.')\n                before_version = path[:extension_index]\n                after_version = path[(extension_index + 1):]\n                return '/static/%s.%s.%s' % (before_version, version_hash,\n                                             after_version)\n\n            def parse_url_path(self, url_path):\n                extension_index = url_path.rindex('.')\n                version_index = url_path.rindex('.', 0, extension_index)\n                return '%s%s' % (url_path[:version_index],\n                                 url_path[extension_index:])\n\n            @classmethod\n            def get_absolute_path(cls, settings, path):\n                return 'CustomStaticFileTest:' + path\n\n            def validate_absolute_path(self, root, absolute_path):\n                return absolute_path\n\n            @classmethod\n            def get_content(self, path, start=None, end=None):\n                assert start is None and end is None\n                if path == 'CustomStaticFileTest:foo.txt':\n                    return b'bar'\n                raise Exception(\"unexpected path %r\" % path)\n\n            def get_content_size(self):\n                if self.absolute_path == 'CustomStaticFileTest:foo.txt':\n                    return 3\n                raise Exception(\"unexpected path %r\" % self.absolute_path)\n\n            def get_modified_time(self):\n                return None\n\n            @classmethod\n            def get_version(cls, settings, path):\n                return \"42\"\n\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                self.write(self.static_url(path))\n\n        self.static_handler_class = MyStaticFileHandler\n\n        return [(\"/static_url/(.*)\", StaticUrlHandler)]\n\n    def get_app_kwargs(self):\n        return dict(static_path=\"dummy\",\n                    static_handler_class=self.static_handler_class)\n\n    def test_serve(self):\n        response = self.fetch(\"/static/foo.42.txt\")\n        self.assertEqual(response.body, b\"bar\")\n\n    def test_static_url(self):\n        with ExpectLog(gen_log, \"Could not open static file\", required=False):\n            response = self.fetch(\"/static_url/foo.txt\")\n            self.assertEqual(response.body, b\"/static/foo.42.txt\")\n\n\n@wsgi_safe\nclass HostMatchingTest(WebTestCase):\n    class Handler(RequestHandler):\n        def initialize(self, reply):\n            self.reply = reply\n\n        def get(self):\n            self.write(self.reply)\n\n    def get_handlers(self):\n        return [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"wildcard\"})]\n\n    def test_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n        self.app.add_handlers(\"www.e.*e.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[3]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"wildcard\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.code, 404)\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[2]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.exe.com'})\n        self.assertEqual(response.body, b\"[3]\")\n\n\n@wsgi_safe\nclass DefaultHostMatchingTest(WebTestCase):\n    def get_handlers(self):\n        return []\n\n    def get_app_kwargs(self):\n        return {'default_host': \"www.example.com\"}\n\n    def test_default_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.test.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={\"X-Real-Ip\": \"127.0.0.1\"})\n        self.assertEqual(response.code, 404)\n\n        self.app.default_host = \"www.test.com\"\n\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.body, b\"[2]\")\n\n\n@wsgi_safe\nclass NamedURLSpecGroupsTest(WebTestCase):\n    def get_handlers(self):\n        class EchoHandler(RequestHandler):\n            def get(self, path):\n                self.write(path)\n\n        return [(\"/str/(?P<path>.*)\", EchoHandler),\n                (u\"/unicode/(?P<path>.*)\", EchoHandler)]\n\n    def test_named_urlspec_groups(self):\n        response = self.fetch(\"/str/foo\")\n        self.assertEqual(response.body, b\"foo\")\n\n        response = self.fetch(\"/unicode/bar\")\n        self.assertEqual(response.body, b\"bar\")\n\n\n@wsgi_safe\nclass ClearHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"h1\", \"foo\")\n            self.set_header(\"h2\", \"bar\")\n            self.clear_header(\"h1\")\n            self.clear_header(\"nonexistent\")\n\n    def test_clear_header(self):\n        response = self.fetch(\"/\")\n        self.assertTrue(\"h1\" not in response.headers)\n        self.assertEqual(response.headers[\"h2\"], \"bar\")\n\n\nclass Header204Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(204)\n            self.finish()\n\n    def test_204_headers(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 204)\n        self.assertNotIn(\"Content-Length\", response.headers)\n        self.assertNotIn(\"Transfer-Encoding\", response.headers)\n\n\n@wsgi_safe\nclass Header304Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"Content-Language\", \"en_US\")\n            self.write(\"hello\")\n\n    def test_304_headers(self):\n        response1 = self.fetch('/')\n        self.assertEqual(response1.headers[\"Content-Length\"], \"5\")\n        self.assertEqual(response1.headers[\"Content-Language\"], \"en_US\")\n\n        response2 = self.fetch('/', headers={\n            'If-None-Match': response1.headers[\"Etag\"]})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue(\"Content-Length\" not in response2.headers)\n        self.assertTrue(\"Content-Language\" not in response2.headers)\n        # Not an entity header, but should not be added to 304s by chunking\n        self.assertTrue(\"Transfer-Encoding\" not in response2.headers)\n\n\n@wsgi_safe\nclass StatusReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            reason = self.request.arguments.get('reason', [])\n            self.set_status(int(self.get_argument('code')),\n                            reason=reason[0] if reason else None)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_status(self):\n        response = self.fetch(\"/?code=304\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Not Modified\")\n        response = self.fetch(\"/?code=304&reason=Foo\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Foo\")\n        response = self.fetch(\"/?code=682&reason=Bar\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Bar\")\n        response = self.fetch(\"/?code=682\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Unknown\")\n\n\n@wsgi_safe\nclass DateHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(\"hello\")\n\n    def test_date_header(self):\n        response = self.fetch('/')\n        header_date = datetime.datetime(\n            *email.utils.parsedate(response.headers['Date'])[:6])\n        self.assertTrue(header_date - datetime.datetime.utcnow() <\n                        datetime.timedelta(seconds=2))\n\n\n@wsgi_safe\nclass RaiseWithReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            raise HTTPError(682, reason=\"Foo\")\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_raise_with_reason(self):\n        response = self.fetch(\"/\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Foo\")\n        self.assertIn(b'682: Foo', response.body)\n\n    def test_httperror_str(self):\n        self.assertEqual(str(HTTPError(682, reason=\"Foo\")), \"HTTP 682: Foo\")\n\n    def test_httperror_str_from_httputil(self):\n        self.assertEqual(str(HTTPError(682)), \"HTTP 682: Unknown\")\n\n\n@wsgi_safe\nclass ErrorHandlerXSRFTest(WebTestCase):\n    def get_handlers(self):\n        # note that if the handlers list is empty we get the default_host\n        # redirect fallback instead of a 404, so test with both an\n        # explicitly defined error handler and an implicit 404.\n        return [('/error', ErrorHandler, dict(status_code=417))]\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def test_error_xsrf(self):\n        response = self.fetch('/error', method='POST', body='')\n        self.assertEqual(response.code, 417)\n\n    def test_404_xsrf(self):\n        response = self.fetch('/404', method='POST', body='')\n        self.assertEqual(response.code, 404)\n\n\n@wsgi_safe\nclass GzipTestCase(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            for v in self.get_arguments('vary'):\n                self.add_header('Vary', v)\n            # Must write at least MIN_LENGTH bytes to activate compression.\n            self.write('hello world' + ('!' * GZipContentEncoding.MIN_LENGTH))\n\n    def get_app_kwargs(self):\n        return dict(\n            gzip=True,\n            static_path=os.path.join(os.path.dirname(__file__), 'static'))\n\n    def assert_compressed(self, response):\n        # simple_httpclient renames the content-encoding header;\n        # curl_httpclient doesn't.\n        self.assertEqual(\n            response.headers.get(\n                'Content-Encoding',\n                response.headers.get('X-Consumed-Content-Encoding')),\n            'gzip')\n\n    def test_gzip(self):\n        response = self.fetch('/')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_static(self):\n        # The streaming responses in StaticFileHandler have subtle\n        # interactions with the gzip output so test this case separately.\n        response = self.fetch('/robots.txt')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_not_requested(self):\n        response = self.fetch('/', use_gzip=False)\n        self.assertNotIn('Content-Encoding', response.headers)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_vary_already_present(self):\n        response = self.fetch('/?vary=Accept-Language')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Accept-Encoding'])\n\n    def test_vary_already_present_multiple(self):\n        # Regression test for https://github.com/tornadoweb/tornado/issues/1670\n        response = self.fetch('/?vary=Accept-Language&vary=Cookie')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Cookie', 'Accept-Encoding'])\n\n\n@wsgi_safe\nclass PathArgsInPrepareTest(WebTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.write(dict(args=self.path_args, kwargs=self.path_kwargs))\n\n        def get(self, path):\n            assert path == 'foo'\n            self.finish()\n\n    def get_handlers(self):\n        return [('/pos/(.*)', self.Handler),\n                ('/kw/(?P<path>.*)', self.Handler)]\n\n    def test_pos(self):\n        response = self.fetch('/pos/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': ['foo'], 'kwargs': {}})\n\n    def test_kw(self):\n        response = self.fetch('/kw/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': [], 'kwargs': {'path': 'foo'}})\n\n\n@wsgi_safe\nclass ClearAllCookiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.clear_all_cookies()\n            self.write('ok')\n\n    def test_clear_all_cookies(self):\n        response = self.fetch('/', headers={'Cookie': 'foo=bar; baz=xyzzy'})\n        set_cookies = sorted(response.headers.get_list('Set-Cookie'))\n        # Python 3.5 sends 'baz=\"\";'; older versions use 'baz=;'\n        self.assertTrue(set_cookies[0].startswith('baz=;') or\n                        set_cookies[0].startswith('baz=\"\";'))\n        self.assertTrue(set_cookies[1].startswith('foo=;') or\n                        set_cookies[1].startswith('foo=\"\";'))\n\n\nclass PermissionError(Exception):\n    pass\n\n\n@wsgi_safe\nclass ExceptionHandlerTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            exc = self.get_argument('exc')\n            if exc == 'http':\n                raise HTTPError(410, \"no longer here\")\n            elif exc == 'zero':\n                1 / 0\n            elif exc == 'permission':\n                raise PermissionError('not allowed')\n\n        def write_error(self, status_code, **kwargs):\n            if 'exc_info' in kwargs:\n                typ, value, tb = kwargs['exc_info']\n                if isinstance(value, PermissionError):\n                    self.set_status(403)\n                    self.write('PermissionError')\n                    return\n            RequestHandler.write_error(self, status_code, **kwargs)\n\n        def log_exception(self, typ, value, tb):\n            if isinstance(value, PermissionError):\n                app_log.warning('custom logging for PermissionError: %s',\n                                value.args[0])\n            else:\n                RequestHandler.log_exception(self, typ, value, tb)\n\n    def test_http_error(self):\n        # HTTPErrors are logged as warnings with no stack trace.\n        # TODO: extend ExpectLog to test this more precisely\n        with ExpectLog(gen_log, '.*no longer here'):\n            response = self.fetch('/?exc=http')\n            self.assertEqual(response.code, 410)\n\n    def test_unknown_error(self):\n        # Unknown errors are logged as errors with a stack trace.\n        with ExpectLog(app_log, 'Uncaught exception'):\n            response = self.fetch('/?exc=zero')\n            self.assertEqual(response.code, 500)\n\n    def test_known_error(self):\n        # log_exception can override logging behavior, and write_error\n        # can override the response.\n        with ExpectLog(app_log,\n                       'custom logging for PermissionError: not allowed'):\n            response = self.fetch('/?exc=permission')\n            self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass BuggyLoggingTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            1 / 0\n\n        def log_exception(self, typ, value, tb):\n            1 / 0\n\n    def test_buggy_log_exception(self):\n        # Something gets logged even though the application's\n        # logger is broken.\n        with ExpectLog(app_log, '.*'):\n            self.fetch('/')\n\n\n@wsgi_safe\nclass UIMethodUIModuleTest(SimpleHandlerTestCase):\n    \"\"\"Test that UI methods and modules are created correctly and\n    associated with the handler.\n    \"\"\"\n    class Handler(RequestHandler):\n        def get(self):\n            self.render('foo.html')\n\n        def value(self):\n            return self.get_argument(\"value\")\n\n    def get_app_kwargs(self):\n        def my_ui_method(handler, x):\n            return \"In my_ui_method(%s) with handler value %s.\" % (\n                x, handler.value())\n\n        class MyModule(UIModule):\n            def render(self, x):\n                return \"In MyModule(%s) with handler value %s.\" % (\n                    x, self.handler.value())\n\n        loader = DictLoader({\n            'foo.html': '{{ my_ui_method(42) }} {% module MyModule(123) %}',\n        })\n        return dict(template_loader=loader,\n                    ui_methods={'my_ui_method': my_ui_method},\n                    ui_modules={'MyModule': MyModule})\n\n    def tearDown(self):\n        super(UIMethodUIModuleTest, self).tearDown()\n        # TODO: fix template loader caching so this isn't necessary.\n        RequestHandler._template_loaders.clear()\n\n    def test_ui_method(self):\n        response = self.fetch('/?value=asdf')\n        self.assertEqual(response.body,\n                         b'In my_ui_method(42) with handler value asdf. '\n                         b'In MyModule(123) with handler value asdf.')\n\n\n@wsgi_safe\nclass GetArgumentErrorTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            try:\n                self.get_argument('foo')\n                self.write({})\n            except MissingArgumentError as e:\n                self.write({'arg_name': e.arg_name,\n                            'log_message': e.log_message})\n\n    def test_catch_error(self):\n        response = self.fetch('/')\n        self.assertEqual(json_decode(response.body),\n                         {'arg_name': 'foo',\n                          'log_message': 'Missing argument foo'})\n\n\nclass MultipleExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        exc_count = 0\n\n        @asynchronous\n        def get(self):\n            from tornado.ioloop import IOLoop\n            IOLoop.current().add_callback(lambda: 1 / 0)\n            IOLoop.current().add_callback(lambda: 1 / 0)\n\n        def log_exception(self, typ, value, tb):\n            MultipleExceptionTest.Handler.exc_count += 1\n\n    def test_multi_exception(self):\n        # This test verifies that multiple exceptions raised into the same\n        # ExceptionStackContext do not generate extraneous log entries\n        # due to \"Cannot send error response after headers written\".\n        # log_exception is called, but it does not proceed to send_error.\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        # Each of our two requests generated two exceptions, we should have\n        # seen at least three of them by now (the fourth may still be\n        # in the queue).\n        self.assertGreater(MultipleExceptionTest.Handler.exc_count, 2)\n\n\n@wsgi_safe\nclass SetLazyPropertiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.current_user = 'Ben'\n            self.locale = locale.get('en_US')\n\n        def get_user_locale(self):\n            raise NotImplementedError()\n\n        def get_current_user(self):\n            raise NotImplementedError()\n\n        def get(self):\n            self.write('Hello %s (%s)' % (self.current_user, self.locale.code))\n\n    def test_set_properties(self):\n        # Ensure that current_user can be assigned to normally for apps\n        # that want to forgo the lazy get_current_user property\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'Hello Ben (en_US)')\n\n\n@wsgi_safe\nclass GetCurrentUserTest(WebTestCase):\n    def get_app_kwargs(self):\n        class WithoutUserModule(UIModule):\n            def render(self):\n                return ''\n\n        class WithUserModule(UIModule):\n            def render(self):\n                return str(self.current_user)\n\n        loader = DictLoader({\n            'without_user.html': '',\n            'with_user.html': '{{ current_user }}',\n            'without_user_module.html': '{% module WithoutUserModule() %}',\n            'with_user_module.html': '{% module WithUserModule() %}',\n        })\n        return dict(template_loader=loader,\n                    ui_modules={'WithUserModule': WithUserModule,\n                                'WithoutUserModule': WithoutUserModule})\n\n    def tearDown(self):\n        super(GetCurrentUserTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        class CurrentUserHandler(RequestHandler):\n            def prepare(self):\n                self.has_loaded_current_user = False\n\n            def get_current_user(self):\n                self.has_loaded_current_user = True\n                return ''\n\n        class WithoutUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('without_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('with_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class CurrentUserModuleHandler(CurrentUserHandler):\n            def get_template_namespace(self):\n                # If RequestHandler.get_template_namespace is called, then\n                # get_current_user is evaluated. Until #820 is fixed, this\n                # is a small hack to circumvent the issue.\n                return self.ui\n\n        class WithoutUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('without_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('with_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        return [('/without_user', WithoutUserHandler),\n                ('/with_user', WithUserHandler),\n                ('/without_user_module', WithoutUserModuleHandler),\n                ('/with_user_module', WithUserModuleHandler)]\n\n    @unittest.skip('needs fix')\n    def test_get_current_user_is_lazy(self):\n        # TODO: Make this test pass. See #820.\n        response = self.fetch('/without_user')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_works(self):\n        response = self.fetch('/with_user')\n        self.assertEqual(response.body, b'True')\n\n    def test_get_current_user_from_ui_module_is_lazy(self):\n        response = self.fetch('/without_user_module')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_from_ui_module_works(self):\n        response = self.fetch('/with_user_module')\n        self.assertEqual(response.body, b'True')\n\n\n@wsgi_safe\nclass UnimplementedHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        pass\n\n    def test_unimplemented_standard_methods(self):\n        for method in ['HEAD', 'GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.code, 405)\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.code, 405)\n\n\nclass UnimplementedNonStandardMethodsTest(SimpleHandlerTestCase):\n    # wsgiref.validate complains about unknown methods in a way that makes\n    # this test not wsgi_safe.\n    class Handler(RequestHandler):\n        def other(self):\n            # Even though this method exists, it won't get called automatically\n            # because it is not in SUPPORTED_METHODS.\n            self.write('other')\n\n    def test_unimplemented_patch(self):\n        # PATCH is recently standardized; Tornado supports it by default\n        # but wsgiref.validate doesn't like it.\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.code, 405)\n\n    def test_unimplemented_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.code, 405)\n\n\n@wsgi_safe\nclass AllHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def method(self):\n            self.write(self.request.method)\n\n        get = delete = options = post = put = method\n\n    def test_standard_methods(self):\n        response = self.fetch('/', method='HEAD')\n        self.assertEqual(response.body, b'')\n        for method in ['GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.body, utf8(method))\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.body, utf8(method))\n\n\nclass PatchMethodTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        SUPPORTED_METHODS = RequestHandler.SUPPORTED_METHODS + ('OTHER',)\n\n        def patch(self):\n            self.write('patch')\n\n        def other(self):\n            self.write('other')\n\n    def test_patch(self):\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.body, b'patch')\n\n    def test_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.body, b'other')\n\n\n@wsgi_safe\nclass FinishInPrepareTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.finish('done')\n\n        def get(self):\n            # It's difficult to assert for certain that a method did not\n            # or will not be called in an asynchronous context, but this\n            # will be logged noisily if it is reached.\n            raise Exception('should not reach this method')\n\n    def test_finish_in_prepare(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'done')\n\n\n@wsgi_safe\nclass Default404Test(WebTestCase):\n    def get_handlers(self):\n        # If there are no handlers at all a default redirect handler gets added.\n        return [('/foo', RequestHandler)]\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body,\n                         b'<html><title>404: Not Found</title>'\n                         b'<body>404: Not Found</body></html>')\n\n\n@wsgi_safe\nclass Custom404Test(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        class Custom404Handler(RequestHandler):\n            def get(self):\n                self.set_status(404)\n                self.write('custom 404 response')\n\n        return dict(default_handler_class=Custom404Handler)\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body, b'custom 404 response')\n\n\n@wsgi_safe\nclass DefaultHandlerArgumentsTest(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        return dict(default_handler_class=ErrorHandler,\n                    default_handler_args=dict(status_code=403))\n\n    def test_403(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass HandlerByNameTest(WebTestCase):\n    def get_handlers(self):\n        # All three are equivalent.\n        return [('/hello1', HelloHandler),\n                ('/hello2', 'tornado.test.web_test.HelloHandler'),\n                url('/hello3', 'tornado.test.web_test.HelloHandler'),\n                ]\n\n    def test_handler_by_name(self):\n        resp = self.fetch('/hello1')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello2')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello3')\n        self.assertEqual(resp.body, b'hello')\n\n\nclass StreamingRequestBodyTest(WebTestCase):\n    def get_handlers(self):\n        @stream_request_body\n        class StreamingBodyHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def prepare(self):\n                self.test.prepared.set_result(None)\n\n            def data_received(self, data):\n                self.test.data.set_result(data)\n\n            def get(self):\n                self.test.finished.set_result(None)\n                self.write({})\n\n        @stream_request_body\n        class EarlyReturnHandler(RequestHandler):\n            def prepare(self):\n                # If we finish the response in prepare, it won't continue to\n                # the (non-existent) data_received.\n                raise HTTPError(401)\n\n        @stream_request_body\n        class CloseDetectionHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def on_connection_close(self):\n                super(CloseDetectionHandler, self).on_connection_close()\n                self.test.close_future.set_result(None)\n\n        return [('/stream_body', StreamingBodyHandler, dict(test=self)),\n                ('/early_return', EarlyReturnHandler),\n                ('/close_detection', CloseDetectionHandler, dict(test=self))]\n\n    def connect(self, url, connection_close):\n        # Use a raw connection so we can control the sending of data.\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        stream = IOStream(s)\n        stream.write(b\"GET \" + url + b\" HTTP/1.1\\r\\n\")\n        if connection_close:\n            stream.write(b\"Connection: close\\r\\n\")\n        stream.write(b\"Transfer-Encoding: chunked\\r\\n\\r\\n\")\n        return stream\n\n    @gen_test\n    def test_streaming_body(self):\n        self.prepared = Future()\n        self.data = Future()\n        self.finished = Future()\n\n        stream = self.connect(b\"/stream_body\", connection_close=True)\n        yield self.prepared\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        # Ensure the first chunk is received before we send the second.\n        data = yield self.data\n        self.assertEqual(data, b\"asdf\")\n        self.data = Future()\n        stream.write(b\"4\\r\\nqwer\\r\\n\")\n        data = yield self.data\n        self.assertEquals(data, b\"qwer\")\n        stream.write(b\"0\\r\\n\")\n        yield self.finished\n        data = yield gen.Task(stream.read_until_close)\n        # This would ideally use an HTTP1Connection to read the response.\n        self.assertTrue(data.endswith(b\"{}\"))\n        stream.close()\n\n    @gen_test\n    def test_early_return(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_early_return_with_data(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_close_during_upload(self):\n        self.close_future = Future()\n        stream = self.connect(b\"/close_detection\", connection_close=False)\n        stream.close()\n        yield self.close_future\n\n\n# Each method in this handler returns a yieldable object and yields to the\n# IOLoop so the future is not immediately ready.  Ensure that the\n# yieldables are respected and no method is called before the previous\n# one has completed.\n@stream_request_body\nclass BaseFlowControlHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n        self.method = None\n        self.methods = []\n\n    @contextlib.contextmanager\n    def in_method(self, method):\n        if self.method is not None:\n            self.test.fail(\"entered method %s while in %s\" %\n                           (method, self.method))\n        self.method = method\n        self.methods.append(method)\n        try:\n            yield\n        finally:\n            self.method = None\n\n    @gen.coroutine\n    def prepare(self):\n        # Note that asynchronous prepare() does not block data_received,\n        # so we don't use in_method here.\n        self.methods.append('prepare')\n        yield gen.Task(IOLoop.current().add_callback)\n\n    @gen.coroutine\n    def post(self):\n        with self.in_method('post'):\n            yield gen.Task(IOLoop.current().add_callback)\n        self.write(dict(methods=self.methods))\n\n\nclass BaseStreamingRequestFlowControlTest(object):\n    def get_httpserver_options(self):\n        # Use a small chunk size so flow control is relevant even though\n        # all the data arrives at once.\n        return dict(chunk_size=10, decompress_request=True)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't support body_producer.\n        return SimpleAsyncHTTPClient()\n\n    # Test all the slightly different code paths for fixed, chunked, etc bodies.\n    def test_flow_control_fixed_body(self):\n        response = self.fetch('/', body='abcdefghijklmnopqrstuvwxyz',\n                              method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_chunked_body(self):\n        chunks = [b'abcd', b'efgh', b'ijkl']\n\n        @gen.coroutine\n        def body_producer(write):\n            for i in chunks:\n                yield write(i)\n        response = self.fetch('/', body_producer=body_producer, method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_compressed_body(self):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(b'abcdefghijklmnopqrstuvwxyz')\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        response = self.fetch('/', body=compressed_body, method='POST',\n                              headers={'Content-Encoding': 'gzip'})\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n\nclass DecoratedStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class DecoratedFlowControlHandler(BaseFlowControlHandler):\n            @gen.coroutine\n            def data_received(self, data):\n                with self.in_method('data_received'):\n                    yield gen.Task(IOLoop.current().add_callback)\n        return [('/', DecoratedFlowControlHandler, dict(test=self))]\n\n\n@skipBefore35\nclass NativeStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class NativeFlowControlHandler(BaseFlowControlHandler):\n            data_received = exec_test(globals(), locals(), \"\"\"\n            async def data_received(self, data):\n                with self.in_method('data_received'):\n                    await gen.Task(IOLoop.current().add_callback)\n            \"\"\")[\"data_received\"]\n        return [('/', NativeFlowControlHandler, dict(test=self))]\n\n\n@wsgi_safe\nclass IncorrectContentLengthTest(SimpleHandlerTestCase):\n    def get_handlers(self):\n        test = self\n        self.server_error = None\n\n        # Manually set a content-length that doesn't match the actual content.\n        class TooHigh(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"42\")\n                try:\n                    self.finish(\"ok\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        class TooLow(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"2\")\n                try:\n                    self.finish(\"hello\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        return [('/high', TooHigh),\n                ('/low', TooLow)]\n\n    def test_content_length_too_high(self):\n        # When the content-length is too high, the connection is simply\n        # closed without completing the response.  An error is logged on\n        # the server.\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/high\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write 40 bytes less than Content-Length\")\n\n    def test_content_length_too_low(self):\n        # When the content-length is too low, the connection is closed\n        # without writing the last chunk, so the client never sees the request\n        # complete (which would be a framing error).\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/low\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write more data than Content-Length\")\n\n\nclass ClientCloseTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            if self.request.version.startswith('HTTP/1'):\n                # Simulate a connection closed by the client during\n                # request processing.  The client will see an error, but the\n                # server should respond gracefully (without logging errors\n                # because we were unable to write out as many bytes as\n                # Content-Length said we would)\n                self.request.connection.stream.close()\n                self.write('hello')\n            else:\n                # TODO: add a HTTP2-compatible version of this test.\n                self.write('requires HTTP/1.x')\n\n    def test_client_close(self):\n        response = self.fetch('/')\n        if response.body == b'requires HTTP/1.x':\n            self.skipTest('requires HTTP/1.x')\n        self.assertEqual(response.code, 599)\n\n\nclass SignedValueTest(unittest.TestCase):\n    SECRET = \"It's a secret to everybody\"\n    SECRET_DICT = {0: \"asdfbasdf\", 1: \"12312312\", 2: \"2342342\"}\n\n    def past(self):\n        return self.present() - 86400 * 32\n\n    def present(self):\n        return 1300000000\n\n    def test_known_values(self):\n        signed_v1 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=1, clock=self.present)\n        self.assertEqual(\n            signed_v1,\n            b\"dmFsdWU=|1300000000|31c934969f53e48164c50768b40cbd7e2daaaa4f\")\n\n        signed_v2 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=2, clock=self.present)\n        self.assertEqual(\n            signed_v2,\n            b\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n            b\"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\")\n\n        signed_default = create_signed_value(SignedValueTest.SECRET,\n                                             \"key\", \"value\", clock=self.present)\n        self.assertEqual(signed_default, signed_v2)\n\n        decoded_v1 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v1, min_version=1,\n                                         clock=self.present)\n        self.assertEqual(decoded_v1, b\"value\")\n\n        decoded_v2 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v2, min_version=2,\n                                         clock=self.present)\n        self.assertEqual(decoded_v2, b\"value\")\n\n    def test_name_swap(self):\n        signed1 = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                      clock=self.present)\n        signed2 = create_signed_value(SignedValueTest.SECRET, \"key2\", \"value\",\n                                      clock=self.present)\n        # Try decoding each string with the other's \"name\"\n        decoded1 = decode_signed_value(SignedValueTest.SECRET, \"key2\", signed1,\n                                       clock=self.present)\n        self.assertIs(decoded1, None)\n        decoded2 = decode_signed_value(SignedValueTest.SECRET, \"key1\", signed2,\n                                       clock=self.present)\n        self.assertIs(decoded2, None)\n\n    def test_expired(self):\n        signed = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                     clock=self.past)\n        decoded_past = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                           signed, clock=self.past)\n        self.assertEqual(decoded_past, b\"value\")\n        decoded_present = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                              signed, clock=self.present)\n        self.assertIs(decoded_present, None)\n\n    def test_payload_tampering(self):\n        # These cookies are variants of the one in test_known_values.\n        sig = \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"\n\n        def validate(prefix):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # Change key version\n        self.assertFalse(validate(\"2|1:1|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too short)\n        self.assertFalse(validate(\"2|1:0|10:130000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too long)\n        self.assertFalse(validate(\"2|1:0|10:1300000000|3:keey|8:dmFsdWU=|\"))\n\n    def test_signature_tampering(self):\n        prefix = \"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n\n        def validate(sig):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # All zeros\n        self.assertFalse(validate(\"0\" * 32))\n        # Change one character\n        self.assertFalse(validate(\n            \"4d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # Change another character\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e153\"))\n        # Truncate\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e15\"))\n        # Lengthen\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e1538\"))\n\n    def test_non_ascii(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET, \"key\", value,\n                                     clock=self.present)\n        decoded = decode_signed_value(SignedValueTest.SECRET, \"key\", signed,\n                                      clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_non_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_invalid_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        newkeys = SignedValueTest.SECRET_DICT.copy()\n        newkeys.pop(0)\n        decoded = decode_signed_value(newkeys,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(None, decoded)\n\n    def test_key_version_retrieval(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        key_version = get_signature_key_version(signed)\n        self.assertEqual(1, key_version)\n\n\n@wsgi_safe\nclass XSRFTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            version = int(self.get_argument(\"version\", \"2\"))\n            # This would be a bad idea in a real app, but in this test\n            # it's fine.\n            self.settings[\"xsrf_cookie_version\"] = version\n            self.write(self.xsrf_token)\n\n        def post(self):\n            self.write(\"ok\")\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def setUp(self):\n        super(XSRFTest, self).setUp()\n        self.xsrf_token = self.get_token()\n\n    def get_token(self, old_token=None, version=None):\n        if old_token is not None:\n            headers = self.cookie_headers(old_token)\n        else:\n            headers = None\n        response = self.fetch(\n            \"/\" if version is None else (\"/?version=%d\" % version),\n            headers=headers)\n        response.rethrow()\n        return native_str(response.body)\n\n    def cookie_headers(self, token=None):\n        if token is None:\n            token = self.xsrf_token\n        return {\"Cookie\": \"_xsrf=\" + token}\n\n    def test_xsrf_fail_no_token(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\"/\", method=\"POST\", body=b\"\")\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_body_no_cookie(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_argument_invalid_format(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument has invalid format\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(),\n                body=urllib_parse.urlencode(dict(_xsrf='3|')))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_invalid_format(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(token='3|'),\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_no_body(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\n                \"/\", method=\"POST\", body=b\"\",\n                headers=self.cookie_headers())\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_success_short_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='deadbeef')),\n            headers=self.cookie_headers(token='deadbeef'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_non_hex_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='xoxo')),\n            headers=self.cookie_headers(token='xoxo'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_post_body(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_query_string(self):\n        response = self.fetch(\n            \"/?\" + urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            method=\"POST\", body=b\"\",\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_header(self):\n        response = self.fetch(\"/\", method=\"POST\", body=b\"\",\n                              headers=dict({\"X-Xsrftoken\": self.xsrf_token},  # type: ignore\n                                           **self.cookie_headers()))\n        self.assertEqual(response.code, 200)\n\n    def test_distinct_tokens(self):\n        # Every request gets a distinct token.\n        NUM_TOKENS = 10\n        tokens = set()\n        for i in range(NUM_TOKENS):\n            tokens.add(self.get_token())\n        self.assertEqual(len(tokens), NUM_TOKENS)\n\n    def test_cross_user(self):\n        token2 = self.get_token()\n        # Each token can be used to authenticate its own request.\n        for token in (self.xsrf_token, token2):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        # Sending one in the cookie and the other in the body is not allowed.\n        for cookie_token, body_token in ((self.xsrf_token, token2),\n                                         (token2, self.xsrf_token)):\n            with ExpectLog(gen_log, '.*XSRF cookie does not match POST'):\n                response = self.fetch(\n                    \"/\", method=\"POST\",\n                    body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                    headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 403)\n\n    def test_refresh_token(self):\n        token = self.xsrf_token\n        tokens_seen = set([token])\n        # A user's token is stable over time.  Refreshing the page in one tab\n        # might update the cookie while an older tab still has the old cookie\n        # in its DOM.  Simulate this scenario by passing a constant token\n        # in the body and re-querying for the token.\n        for i in range(5):\n            token = self.get_token(token)\n            # Tokens are encoded uniquely each time\n            tokens_seen.add(token)\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        self.assertEqual(len(tokens_seen), 6)\n\n    def test_versioning(self):\n        # Version 1 still produces distinct tokens per request.\n        self.assertNotEqual(self.get_token(version=1),\n                            self.get_token(version=1))\n\n        # Refreshed v1 tokens are all identical.\n        v1_token = self.get_token(version=1)\n        for i in range(5):\n            self.assertEqual(self.get_token(v1_token, version=1), v1_token)\n\n        # Upgrade to a v2 version of the same token\n        v2_token = self.get_token(v1_token)\n        self.assertNotEqual(v1_token, v2_token)\n        # Each v1 token can map to many v2 tokens.\n        self.assertNotEqual(v2_token, self.get_token(v1_token))\n\n        # The tokens are cross-compatible.\n        for cookie_token, body_token in ((v1_token, v2_token),\n                                         (v2_token, v1_token)):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass XSRFCookieKwargsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(self.xsrf_token)\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True,\n                    xsrf_cookie_kwargs=dict(httponly=True))\n\n    def test_xsrf_httponly(self):\n        response = self.fetch(\"/\")\n        self.assertIn('httponly;', response.headers['Set-Cookie'].lower())\n\n\n@wsgi_safe\nclass FinishExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(401)\n            self.set_header('WWW-Authenticate', 'Basic realm=\"something\"')\n            if self.get_argument('finish_value', ''):\n                raise Finish('authentication required')\n            else:\n                self.write('authentication required')\n                raise Finish()\n\n    def test_finish_exception(self):\n        for u in ['/', '/?finish_value=1']:\n            response = self.fetch(u)\n            self.assertEqual(response.code, 401)\n            self.assertEqual('Basic realm=\"something\"',\n                             response.headers.get('WWW-Authenticate'))\n            self.assertEqual(b'authentication required', response.body)\n\n\n@wsgi_safe\nclass DecoratorTest(WebTestCase):\n    def get_handlers(self):\n        class RemoveSlashHandler(RequestHandler):\n            @removeslash\n            def get(self):\n                pass\n\n        class AddSlashHandler(RequestHandler):\n            @addslash\n            def get(self):\n                pass\n\n        return [(\"/removeslash/\", RemoveSlashHandler),\n                (\"/addslash\", AddSlashHandler),\n                ]\n\n    def test_removeslash(self):\n        response = self.fetch(\"/removeslash/\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash\")\n\n        response = self.fetch(\"/removeslash/?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash?foo=bar\")\n\n    def test_addslash(self):\n        response = self.fetch(\"/addslash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/\")\n\n        response = self.fetch(\"/addslash?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/?foo=bar\")\n\n\n@wsgi_safe\nclass CacheTest(WebTestCase):\n    def get_handlers(self):\n        class EtagHandler(RequestHandler):\n            def get(self, computed_etag):\n                self.write(computed_etag)\n\n            def compute_etag(self):\n                return self._write_buffer[0]\n\n        return [\n            ('/etag/(.*)', EtagHandler)\n        ]\n\n    def test_wildcard_etag(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '*'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_strong_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_weak_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_weak_etag_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy3\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def _test_etag(self, computed_etag, etags, status_code):\n        response = self.fetch(\n            '/etag/' + computed_etag,\n            headers={'If-None-Match': etags}\n        )\n        self.assertEqual(response.code, status_code)\n\n\n@wsgi_safe\nclass RequestSummaryTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            # remote_ip is optional, although it's set by\n            # both HTTPServer and WSGIAdapter.\n            # Clobber it to make sure it doesn't break logging.\n            self.request.remote_ip = None\n            self.finish(self._request_summary())\n\n    def test_missing_remote_ip(self):\n        resp = self.fetch(\"/\")\n        self.assertEqual(resp.body, b\"GET / (None)\")\n\n\nclass HTTPErrorTest(unittest.TestCase):\n    def test_copy(self):\n        e = HTTPError(403, reason=\"Go away\")\n        e2 = copy.copy(e)\n        self.assertIsNot(e, e2)\n        self.assertEqual(e.status_code, e2.status_code)\n        self.assertEqual(e.reason, e2.reason)\n\n\nclass ApplicationTest(AsyncTestCase):\n    def test_listen(self):\n        app = Application([])\n        server = app.listen(0, address='127.0.0.1')\n        server.stop()\n\n\nclass URLSpecReverseTest(unittest.TestCase):\n    def test_reverse(self):\n        self.assertEqual('/favicon.ico', url(r'/favicon\\.ico', None).reverse())\n        self.assertEqual('/favicon.ico', url(r'^/favicon\\.ico$', None).reverse())\n\n    def test_non_reversible(self):\n        # URLSpecs are non-reversible if they include non-constant\n        # regex features outside capturing groups. Currently, this is\n        # only strictly enforced for backslash-escaped character\n        # classes.\n        paths = [\n            r'^/api/v\\d+/foo/(\\w+)$',\n        ]\n        for path in paths:\n            # A URLSpec can still be created even if it cannot be reversed.\n            url_spec = url(path, None)\n            try:\n                result = url_spec.reverse()\n                self.fail(\"did not get expected exception when reversing %s. \"\n                          \"result: %s\" % (path, result))\n            except ValueError:\n                pass\n\n    def test_reverse_arguments(self):\n        self.assertEqual('/api/v1/foo/bar',\n                         url(r'^/api/v1/foo/(\\w+)$', None).reverse('bar'))\n\n\nclass RedirectHandlerTest(WebTestCase):\n    def get_handlers(self):\n        return [\n            ('/src', WebRedirectHandler, {'url': '/dst'}),\n            ('/src2', WebRedirectHandler, {'url': '/dst2?foo=bar'}),\n            (r'/(.*?)/(.*?)/(.*)', WebRedirectHandler, {'url': '/{1}/{0}/{2}'})]\n\n    def test_basic_redirect(self):\n        response = self.fetch('/src', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst')\n\n    def test_redirect_with_argument(self):\n        response = self.fetch('/src?foo=bar', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst?foo=bar')\n\n    def test_redirect_with_appending_argument(self):\n        response = self.fetch('/src2?foo2=bar2', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst2?foo=bar&foo2=bar2')\n\n    def test_redirect_pattern(self):\n        response = self.fetch('/a/b/c', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/b/a/c')\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function\nfrom tornado.concurrent import Future\nfrom tornado import gen\nfrom tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str, to_basestring\nfrom tornado.httputil import format_timestamp\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import IOStream\nfrom tornado import locale\nfrom tornado.log import app_log, gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.template import DictLoader\nfrom tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipBefore35, exec_test\nfrom tornado.util import ObjectDict, unicode_type, timedelta_to_seconds, PY3\nfrom tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish, removeslash, addslash, RedirectHandler as WebRedirectHandler, get_signature_key_version, GZipContentEncoding\n\nimport binascii\nimport contextlib\nimport copy\nimport datetime\nimport email.utils\nimport gzip\nfrom io import BytesIO\nimport itertools\nimport logging\nimport os\nimport re\nimport socket\n\nif PY3:\n    import urllib.parse as urllib_parse  # py3\nelse:\n    import urllib as urllib_parse  # py2\n\nwsgi_safe_tests = []\n\n\ndef relpath(*a):\n    return os.path.join(os.path.dirname(__file__), *a)\n\n\ndef wsgi_safe(cls):\n    wsgi_safe_tests.append(cls)\n    return cls\n\n\nclass WebTestCase(AsyncHTTPTestCase):\n    \"\"\"Base class for web tests that also supports WSGI mode.\n\n    Override get_handlers and get_app_kwargs instead of get_app.\n    Append to wsgi_safe to have it run in wsgi_test as well.\n    \"\"\"\n    def get_app(self):\n        self.app = Application(self.get_handlers(), **self.get_app_kwargs())\n        return self.app\n\n    def get_handlers(self):\n        raise NotImplementedError()\n\n    def get_app_kwargs(self):\n        return {}\n\n\nclass SimpleHandlerTestCase(WebTestCase):\n    \"\"\"Simplified base class for tests that work with a single handler class.\n\n    To use, define a nested class named ``Handler``.\n    \"\"\"\n    def get_handlers(self):\n        return [('/', self.Handler)]\n\n\nclass HelloHandler(RequestHandler):\n    def get(self):\n        self.write('hello')\n\n\nclass CookieTestRequestHandler(RequestHandler):\n    # stub out enough methods to make the secure_cookie functions work\n    def __init__(self, cookie_secret='0123456789', key_version=None):\n        # don't call super.__init__\n        self._cookies = {}\n        if key_version is None:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret))\n        else:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret,\n                                                        key_version=key_version))\n\n    def get_cookie(self, name):\n        return self._cookies.get(name)\n\n    def set_cookie(self, name, value, expires_days=None):\n        self._cookies[name] = value\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV1Test(unittest.TestCase):\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1),\n                         b'bar')\n\n    def test_cookie_tampering_future_timestamp(self):\n        handler = CookieTestRequestHandler()\n        # this string base64-encodes to '12345678'\n        handler.set_secure_cookie('foo', binascii.a2b_hex(b'd76df8e7aefc'),\n                                  version=1)\n        cookie = handler._cookies['foo']\n        match = re.match(br'12345678\\|([0-9]+)\\|([0-9a-f]+)', cookie)\n        self.assertTrue(match)\n        timestamp = match.group(1)\n        sig = match.group(2)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '12345678', timestamp),\n            sig)\n        # shifting digits from payload to timestamp doesn't alter signature\n        # (this is not desirable behavior, just confirming that that's how it\n        # works)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '1234', b'5678' + timestamp),\n            sig)\n        # tamper with the cookie\n        handler._cookies['foo'] = utf8('1234|5678%s|%s' % (\n            to_basestring(timestamp), to_basestring(sig)))\n        # it gets rejected\n        with ExpectLog(gen_log, \"Cookie timestamp in future\"):\n            self.assertTrue(\n                handler.get_secure_cookie('foo', min_version=1) is None)\n\n    def test_arbitrary_bytes(self):\n        # Secure cookies accept arbitrary data (which is base64 encoded).\n        # Note that normal cookies accept only a subset of ascii.\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'\\xe9', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1), b'\\xe9')\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV2Test(unittest.TestCase):\n    KEY_VERSIONS = {\n        0: 'ajklasdf0ojaisdf',\n        1: 'aslkjasaolwkjsdf'\n    }\n\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=2)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=2), b'bar')\n\n    def test_key_version_roundtrip(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_roundtrip_differing_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=1)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_increment_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_invalidate_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_key_versions = self.KEY_VERSIONS.copy()\n        new_key_versions.pop(0)\n        new_handler = CookieTestRequestHandler(cookie_secret=new_key_versions,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), None)\n\n\nclass CookieTest(WebTestCase):\n    def get_handlers(self):\n        class SetCookieHandler(RequestHandler):\n            def get(self):\n                # Try setting cookies with different argument types\n                # to ensure that everything gets encoded correctly\n                self.set_cookie(\"str\", \"asdf\")\n                self.set_cookie(\"unicode\", u\"qwer\")\n                self.set_cookie(\"bytes\", b\"zxcv\")\n\n        class GetCookieHandler(RequestHandler):\n            def get(self):\n                self.write(self.get_cookie(\"foo\", \"default\"))\n\n        class SetCookieDomainHandler(RequestHandler):\n            def get(self):\n                # unicode domain and path arguments shouldn't break things\n                # either (see bug #285)\n                self.set_cookie(\"unicode_args\", \"blah\", domain=u\"foo.com\",\n                                path=u\"/foo\")\n\n        class SetCookieSpecialCharHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"equals\", \"a=b\")\n                self.set_cookie(\"semicolon\", \"a;b\")\n                self.set_cookie(\"quote\", 'a\"b')\n\n        class SetCookieOverwriteHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"b\", domain=\"example.com\")\n                self.set_cookie(\"c\", \"d\", domain=\"example.com\")\n                # A second call with the same name clobbers the first.\n                # Attributes from the first call are not carried over.\n                self.set_cookie(\"a\", \"e\")\n\n        class SetCookieMaxAgeHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", max_age=10)\n\n        class SetCookieExpiresDaysHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", expires_days=10)\n\n        class SetCookieFalsyFlags(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"1\", secure=True)\n                self.set_cookie(\"b\", \"1\", secure=False)\n                self.set_cookie(\"c\", \"1\", httponly=True)\n                self.set_cookie(\"d\", \"1\", httponly=False)\n\n        return [(\"/set\", SetCookieHandler),\n                (\"/get\", GetCookieHandler),\n                (\"/set_domain\", SetCookieDomainHandler),\n                (\"/special_char\", SetCookieSpecialCharHandler),\n                (\"/set_overwrite\", SetCookieOverwriteHandler),\n                (\"/set_max_age\", SetCookieMaxAgeHandler),\n                (\"/set_expires_days\", SetCookieExpiresDaysHandler),\n                (\"/set_falsy_flags\", SetCookieFalsyFlags)\n                ]\n\n    def test_set_cookie(self):\n        response = self.fetch(\"/set\")\n        self.assertEqual(sorted(response.headers.get_list(\"Set-Cookie\")),\n                         [\"bytes=zxcv; Path=/\",\n                          \"str=asdf; Path=/\",\n                          \"unicode=qwer; Path=/\",\n                          ])\n\n    def test_get_cookie(self):\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"foo=bar\"})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": 'foo=\"bar\"'})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"/=exception;\"})\n        self.assertEqual(response.body, b\"default\")\n\n    def test_set_cookie_domain(self):\n        response = self.fetch(\"/set_domain\")\n        self.assertEqual(response.headers.get_list(\"Set-Cookie\"),\n                         [\"unicode_args=blah; Domain=foo.com; Path=/foo\"])\n\n    def test_cookie_special_char(self):\n        response = self.fetch(\"/special_char\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        self.assertEqual(len(headers), 3)\n        self.assertEqual(headers[0], 'equals=\"a=b\"; Path=/')\n        self.assertEqual(headers[1], 'quote=\"a\\\\\"b\"; Path=/')\n        # python 2.7 octal-escapes the semicolon; older versions leave it alone\n        self.assertTrue(headers[2] in ('semicolon=\"a;b\"; Path=/',\n                                       'semicolon=\"a\\\\073b\"; Path=/'),\n                        headers[2])\n\n        data = [('foo=a=b', 'a=b'),\n                ('foo=\"a=b\"', 'a=b'),\n                ('foo=\"a;b\"', '\"a'),  # even quoted, \";\" is a delimiter\n                ('foo=a\\\\073b', 'a\\\\073b'),  # escapes only decoded in quotes\n                ('foo=\"a\\\\073b\"', 'a;b'),\n                ('foo=\"a\\\\\"b\"', 'a\"b'),\n                ]\n        for header, expected in data:\n            logging.debug(\"trying %r\", header)\n            response = self.fetch(\"/get\", headers={\"Cookie\": header})\n            self.assertEqual(response.body, utf8(expected))\n\n    def test_set_cookie_overwrite(self):\n        response = self.fetch(\"/set_overwrite\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"a=e; Path=/\", \"c=d; Domain=example.com; Path=/\"])\n\n    def test_set_cookie_max_age(self):\n        response = self.fetch(\"/set_max_age\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"foo=bar; Max-Age=10; Path=/\"])\n\n    def test_set_cookie_expires_days(self):\n        response = self.fetch(\"/set_expires_days\")\n        header = response.headers.get(\"Set-Cookie\")\n        match = re.match(\"foo=bar; expires=(?P<expires>.+); Path=/\", header)\n        self.assertIsNotNone(match)\n\n        expires = datetime.datetime.utcnow() + datetime.timedelta(days=10)\n        header_expires = datetime.datetime(\n            *email.utils.parsedate(match.groupdict()[\"expires\"])[:6])\n        self.assertTrue(abs(timedelta_to_seconds(expires - header_expires)) < 10)\n\n    def test_set_cookie_false_flags(self):\n        response = self.fetch(\"/set_falsy_flags\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        # The secure and httponly headers are capitalized in py35 and\n        # lowercase in older versions.\n        self.assertEqual(headers[0].lower(), 'a=1; path=/; secure')\n        self.assertEqual(headers[1].lower(), 'b=1; path=/')\n        self.assertEqual(headers[2].lower(), 'c=1; httponly; path=/')\n        self.assertEqual(headers[3].lower(), 'd=1; path=/')\n\n\nclass AuthRedirectRequestHandler(RequestHandler):\n    def initialize(self, login_url):\n        self.login_url = login_url\n\n    def get_login_url(self):\n        return self.login_url\n\n    @authenticated\n    def get(self):\n        # we'll never actually get here because the test doesn't follow redirects\n        self.send_error(500)\n\n\nclass AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2F127.0.0.1%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])\n\n\nclass ConnectionCloseHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n\n    @asynchronous\n    def get(self):\n        self.test.on_handler_waiting()\n\n    def on_connection_close(self):\n        self.test.on_connection_close()\n\n\nclass ConnectionCloseTest(WebTestCase):\n    def get_handlers(self):\n        return [('/', ConnectionCloseHandler, dict(test=self))]\n\n    def test_connection_close(self):\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        self.stream = IOStream(s)\n        self.stream.write(b\"GET / HTTP/1.0\\r\\n\\r\\n\")\n        self.wait()\n\n    def on_handler_waiting(self):\n        logging.debug('handler waiting')\n        self.stream.close()\n\n    def on_connection_close(self):\n        logging.debug('connection closed')\n        self.stop()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self, *path_args):\n        # Type checks: web.py interfaces convert argument values to\n        # unicode strings (by default, but see also decode_argument).\n        # In httpserver.py (i.e. self.request.arguments), they're left\n        # as bytes.  Keys are always native strings.\n        for key in self.request.arguments:\n            if type(key) != str:\n                raise Exception(\"incorrect type for key: %r\" % type(key))\n            for value in self.request.arguments[key]:\n                if type(value) != bytes:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n            for value in self.get_arguments(key):\n                if type(value) != unicode_type:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n        for arg in path_args:\n            if type(arg) != unicode_type:\n                raise Exception(\"incorrect type for path arg: %r\" % type(arg))\n        self.write(dict(path=self.request.path,\n                        path_args=path_args,\n                        args=recursive_unicode(self.request.arguments)))\n\n\nclass RequestEncodingTest(WebTestCase):\n    def get_handlers(self):\n        return [(\"/group/(.*)\", EchoHandler),\n                (\"/slashes/([^/]*)/([^/]*)\", EchoHandler),\n                ]\n\n    def fetch_json(self, path):\n        return json_decode(self.fetch(path).body)\n\n    def test_group_question_mark(self):\n        # Ensure that url-encoded question marks are handled properly\n        self.assertEqual(self.fetch_json('/group/%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={}))\n        self.assertEqual(self.fetch_json('/group/%3F?%3F=%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={'?': ['?']}))\n\n    def test_group_encoding(self):\n        # Path components and query arguments should be decoded the same way\n        self.assertEqual(self.fetch_json('/group/%C3%A9?arg=%C3%A9'),\n                         {u\"path\": u\"/group/%C3%A9\",\n                          u\"path_args\": [u\"\\u00e9\"],\n                          u\"args\": {u\"arg\": [u\"\\u00e9\"]}})\n\n    def test_slashes(self):\n        # Slashes may be escaped to appear as a single \"directory\" in the path,\n        # but they are then unescaped when passed to the get() method.\n        self.assertEqual(self.fetch_json('/slashes/foo/bar'),\n                         dict(path=\"/slashes/foo/bar\",\n                              path_args=[\"foo\", \"bar\"],\n                              args={}))\n        self.assertEqual(self.fetch_json('/slashes/a%2Fb/c%2Fd'),\n                         dict(path=\"/slashes/a%2Fb/c%2Fd\",\n                              path_args=[\"a/b\", \"c/d\"],\n                              args={}))\n\n    def test_error(self):\n        # Percent signs (encoded as %25) should not mess up printf-style\n        # messages in logs\n        with ExpectLog(gen_log, \".*Invalid unicode\"):\n            self.fetch(\"/group/?arg=%25%e9\")\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n\n        self.check_type('status', self.get_status(), int)\n\n        # get_argument is an exception from the general rule of using\n        # type str for non-body data mainly for historical reasons.\n        self.check_type('argument', self.get_argument('foo'), unicode_type)\n        self.check_type('cookie_key', list(self.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.cookies.values())[0].value, str)\n\n        # Secure cookies return bytes because they can contain arbitrary\n        # data, but regular cookies are native strings.\n        if list(self.cookies.keys()) != ['asdf']:\n            raise Exception(\"unexpected values for cookie keys: %r\" %\n                            self.cookies.keys())\n        self.check_type('get_secure_cookie', self.get_secure_cookie('asdf'), bytes)\n        self.check_type('get_cookie', self.get_cookie('asdf'), str)\n\n        self.check_type('xsrf_token', self.xsrf_token, bytes)\n        self.check_type('xsrf_form_html', self.xsrf_form_html(), str)\n\n        self.check_type('reverse_url', self.reverse_url('typecheck', 'foo'), str)\n\n        self.check_type('request_summary', self._request_summary(), str)\n\n    def get(self, path_component):\n        # path_component uses type unicode instead of str for consistency\n        # with get_argument()\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def post(self, path_component):\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass DecodeArgHandler(RequestHandler):\n    def decode_argument(self, value, name=None):\n        if type(value) != bytes:\n            raise Exception(\"unexpected type for value: %r\" % type(value))\n        # use self.request.arguments directly to avoid recursion\n        if 'encoding' in self.request.arguments:\n            return value.decode(to_unicode(self.request.arguments['encoding'][0]))\n        else:\n            return value\n\n    def get(self, arg):\n        def describe(s):\n            if type(s) == bytes:\n                return [\"bytes\", native_str(binascii.b2a_hex(s))]\n            elif type(s) == unicode_type:\n                return [\"unicode\", s]\n            raise Exception(\"unknown type\")\n        self.write({'path': describe(arg),\n                    'query': describe(self.get_argument(\"foo\")),\n                    })\n\n\nclass LinkifyHandler(RequestHandler):\n    def get(self):\n        self.render(\"linkify.html\", message=\"http://example.com\")\n\n\nclass UIModuleResourceHandler(RequestHandler):\n    def get(self):\n        self.render(\"page.html\", entries=[1, 2])\n\n\nclass OptionalPathHandler(RequestHandler):\n    def get(self, path):\n        self.write({\"path\": path})\n\n\nclass FlowControlHandler(RequestHandler):\n    # These writes are too small to demonstrate real flow control,\n    # but at least it shows that the callbacks get run.\n    @asynchronous\n    def get(self):\n        self.write(\"1\")\n        self.flush(callback=self.step2)\n\n    def step2(self):\n        self.write(\"2\")\n        self.flush(callback=self.step3)\n\n    def step3(self):\n        self.write(\"3\")\n        self.finish()\n\n\nclass MultiHeaderHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"x-overwrite\", \"1\")\n        self.set_header(\"X-Overwrite\", 2)\n        self.add_header(\"x-multi\", 3)\n        self.add_header(\"X-Multi\", \"4\")\n\n\nclass RedirectHandler(RequestHandler):\n    def get(self):\n        if self.get_argument('permanent', None) is not None:\n            self.redirect('/', permanent=int(self.get_argument('permanent')))\n        elif self.get_argument('status', None) is not None:\n            self.redirect('/', status=int(self.get_argument('status')))\n        else:\n            raise Exception(\"didn't get permanent or status arguments\")\n\n\nclass EmptyFlushCallbackHandler(RequestHandler):\n    @asynchronous\n    @gen.engine\n    def get(self):\n        # Ensure that the flush callback is run whether or not there\n        # was any output.  The gen.Task and direct yield forms are\n        # equivalent.\n        yield gen.Task(self.flush)  # \"empty\" flush, but writes headers\n        yield gen.Task(self.flush)  # empty flush\n        self.write(\"o\")\n        yield self.flush()  # flushes the \"o\"\n        yield self.flush()  # empty flush\n        self.finish(\"k\")\n\n\nclass HeaderInjectionHandler(RequestHandler):\n    def get(self):\n        try:\n            self.set_header(\"X-Foo\", \"foo\\r\\nX-Bar: baz\")\n            raise Exception(\"Didn't get expected exception\")\n        except ValueError as e:\n            if \"Unsafe header value\" in str(e):\n                self.finish(b\"ok\")\n            else:\n                raise\n\n\nclass GetArgumentHandler(RequestHandler):\n    def prepare(self):\n        if self.get_argument('source', None) == 'query':\n            method = self.get_query_argument\n        elif self.get_argument('source', None) == 'body':\n            method = self.get_body_argument\n        else:\n            method = self.get_argument\n        self.finish(method(\"foo\", \"default\"))\n\n\nclass GetArgumentsHandler(RequestHandler):\n    def prepare(self):\n        self.finish(dict(default=self.get_arguments(\"foo\"),\n                         query=self.get_query_arguments(\"foo\"),\n                         body=self.get_body_arguments(\"foo\")))\n\n\n# This test is shared with wsgi_test.py\n@wsgi_safe\nclass WSGISafeWebTest(WebTestCase):\n    COOKIE_SECRET = \"WebTest.COOKIE_SECRET\"\n\n    def get_app_kwargs(self):\n        loader = DictLoader({\n            \"linkify.html\": \"{% module linkify(message) %}\",\n            \"page.html\": \"\"\"\\\n<html><head></head><body>\n{% for e in entries %}\n{% module Template(\"entry.html\", entry=e) %}\n{% end %}\n</body></html>\"\"\",\n            \"entry.html\": \"\"\"\\\n{{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\", embedded_javascript=\"js_embed()\", css_files=[\"/base.css\", \"/foo.css\"], javascript_files=\"/common.js\", html_head=\"<meta>\", html_body='<script src=\"/analytics.js\"/>') }}\n<div class=\"entry\">...</div>\"\"\",\n        })\n        return dict(template_loader=loader,\n                    autoescape=\"xhtml_escape\",\n                    cookie_secret=self.COOKIE_SECRET)\n\n    def tearDown(self):\n        super(WSGISafeWebTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        urls = [\n            url(\"/typecheck/(.*)\", TypeCheckHandler, name='typecheck'),\n            url(\"/decode_arg/(.*)\", DecodeArgHandler, name='decode_arg'),\n            url(\"/decode_arg_kw/(?P<arg>.*)\", DecodeArgHandler),\n            url(\"/linkify\", LinkifyHandler),\n            url(\"/uimodule_resources\", UIModuleResourceHandler),\n            url(\"/optional_path/(.+)?\", OptionalPathHandler),\n            url(\"/multi_header\", MultiHeaderHandler),\n            url(\"/redirect\", RedirectHandler),\n            url(\"/web_redirect_permanent\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\"}),\n            url(\"/web_redirect\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\", \"permanent\": False}),\n            url(\"//web_redirect_double_slash\", WebRedirectHandler, {\"url\": '/web_redirect_newpath'}),\n            url(\"/header_injection\", HeaderInjectionHandler),\n            url(\"/get_argument\", GetArgumentHandler),\n            url(\"/get_arguments\", GetArgumentsHandler),\n        ]\n        return urls\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n    def test_types(self):\n        cookie_value = to_unicode(create_signed_value(self.COOKIE_SECRET,\n                                                      \"asdf\", \"qwer\"))\n        response = self.fetch(\"/typecheck/asdf?foo=bar\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value})\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck/asdf?foo=bar\", method=\"POST\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value},\n                              body=\"foo=bar\")\n\n    def test_decode_argument(self):\n        # These urls all decode to the same thing\n        urls = [\"/decode_arg/%C3%A9?foo=%C3%A9&encoding=utf-8\",\n                \"/decode_arg/%E9?foo=%E9&encoding=latin1\",\n                \"/decode_arg_kw/%E9?foo=%E9&encoding=latin1\",\n                ]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'\\u00e9'],\n                                    u'query': [u'unicode', u'\\u00e9'],\n                                    })\n\n        response = self.fetch(\"/decode_arg/%C3%A9?foo=%C3%A9\")\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {u'path': [u'bytes', u'c3a9'],\n                                u'query': [u'bytes', u'c3a9'],\n                                })\n\n    def test_decode_argument_invalid_unicode(self):\n        # test that invalid unicode in URLs causes 400, not 500\n        with ExpectLog(gen_log, \".*Invalid unicode.*\"):\n            response = self.fetch(\"/typecheck/invalid%FF\")\n            self.assertEqual(response.code, 400)\n            response = self.fetch(\"/typecheck/invalid?foo=%FF\")\n            self.assertEqual(response.code, 400)\n\n    def test_decode_argument_plus(self):\n        # These urls are all equivalent.\n        urls = [\"/decode_arg/1%20%2B%201?foo=1%20%2B%201&encoding=utf-8\",\n                \"/decode_arg/1%20+%201?foo=1+%2B+1&encoding=utf-8\"]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'1 + 1'],\n                                    u'query': [u'unicode', u'1 + 1'],\n                                    })\n\n    def test_reverse_url(self):\n        self.assertEqual(self.app.reverse_url('decode_arg', 'foo'),\n                         '/decode_arg/foo')\n        self.assertEqual(self.app.reverse_url('decode_arg', 42),\n                         '/decode_arg/42')\n        self.assertEqual(self.app.reverse_url('decode_arg', b'\\xe9'),\n                         '/decode_arg/%E9')\n        self.assertEqual(self.app.reverse_url('decode_arg', u'\\u00e9'),\n                         '/decode_arg/%C3%A9')\n        self.assertEqual(self.app.reverse_url('decode_arg', '1 + 1'),\n                         '/decode_arg/1%20%2B%201')\n\n    def test_uimodule_unescaped(self):\n        response = self.fetch(\"/linkify\")\n        self.assertEqual(response.body,\n                         b\"<a href=\\\"http://example.com\\\">http://example.com</a>\")\n\n    def test_uimodule_resources(self):\n        response = self.fetch(\"/uimodule_resources\")\n        self.assertEqual(response.body, b\"\"\"\\\n<html><head><link href=\"/base.css\" type=\"text/css\" rel=\"stylesheet\"/><link href=\"/foo.css\" type=\"text/css\" rel=\"stylesheet\"/>\n<style type=\"text/css\">\n.entry { margin-bottom: 1em; }\n</style>\n<meta>\n</head><body>\n\n\n<div class=\"entry\">...</div>\n\n\n<div class=\"entry\">...</div>\n\n<script src=\"/common.js\" type=\"text/javascript\"></script>\n<script type=\"text/javascript\">\n//<![CDATA[\njs_embed()\n//]]>\n</script>\n<script src=\"/analytics.js\"/>\n</body></html>\"\"\")\n\n    def test_optional_path(self):\n        self.assertEqual(self.fetch_json(\"/optional_path/foo\"),\n                         {u\"path\": u\"foo\"})\n        self.assertEqual(self.fetch_json(\"/optional_path/\"),\n                         {u\"path\": None})\n\n    def test_multi_header(self):\n        response = self.fetch(\"/multi_header\")\n        self.assertEqual(response.headers[\"x-overwrite\"], \"2\")\n        self.assertEqual(response.headers.get_list(\"x-multi\"), [\"3\", \"4\"])\n\n    def test_redirect(self):\n        response = self.fetch(\"/redirect?permanent=1\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        response = self.fetch(\"/redirect?permanent=0\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        response = self.fetch(\"/redirect?status=307\", follow_redirects=False)\n        self.assertEqual(response.code, 307)\n\n    def test_web_redirect(self):\n        response = self.fetch(\"/web_redirect_permanent\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n        response = self.fetch(\"/web_redirect\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_web_redirect_double_slash(self):\n        response = self.fetch(\"//web_redirect_double_slash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_header_injection(self):\n        response = self.fetch(\"/header_injection\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_get_argument(self):\n        response = self.fetch(\"/get_argument?foo=bar\")\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?foo=\")\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument\")\n        self.assertEqual(response.body, b\"default\")\n\n        # Test merging of query and body arguments.\n        # In singular form, body arguments take precedence over query arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?foo=bar\", method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"hello\")\n        # In plural methods they are merged.\n        response = self.fetch(\"/get_arguments?foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(json_decode(response.body),\n                         dict(default=['bar', 'hello'],\n                              query=['bar'],\n                              body=['hello']))\n\n    def test_get_query_arguments(self):\n        # send as a post so we can ensure the separation between query\n        # string and body arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?source=query&foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?source=query&foo=\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument?source=query\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_get_body_arguments(self):\n        body = urllib_parse.urlencode(dict(foo=\"bar\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n\n        body = urllib_parse.urlencode(dict(foo=\"\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n\n        body = urllib_parse.urlencode(dict())\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_no_gzip(self):\n        response = self.fetch('/get_argument')\n        self.assertNotIn('Accept-Encoding', response.headers.get('Vary', ''))\n        self.assertNotIn('gzip', response.headers.get('Content-Encoding', ''))\n\n\nclass NonWSGIWebTests(WebTestCase):\n    def get_handlers(self):\n        return [(\"/flow_control\", FlowControlHandler),\n                (\"/empty_flush\", EmptyFlushCallbackHandler),\n                ]\n\n    def test_flow_control(self):\n        self.assertEqual(self.fetch(\"/flow_control\").body, b\"123\")\n\n    def test_empty_flush(self):\n        response = self.fetch(\"/empty_flush\")\n        self.assertEqual(response.body, b\"ok\")\n\n\n@wsgi_safe\nclass ErrorResponseTest(WebTestCase):\n    def get_handlers(self):\n        class DefaultHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    raise HTTPError(int(self.get_argument(\"status\")))\n                1 / 0\n\n        class WriteErrorHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    self.send_error(int(self.get_argument(\"status\")))\n                else:\n                    1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                self.set_header(\"Content-Type\", \"text/plain\")\n                if \"exc_info\" in kwargs:\n                    self.write(\"Exception: %s\" % kwargs[\"exc_info\"][0].__name__)\n                else:\n                    self.write(\"Status: %d\" % status_code)\n\n        class FailedWriteErrorHandler(RequestHandler):\n            def get(self):\n                1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                raise Exception(\"exception in write_error\")\n\n        return [url(\"/default\", DefaultHandler),\n                url(\"/write_error\", WriteErrorHandler),\n                url(\"/failed_write_error\", FailedWriteErrorHandler),\n                ]\n\n    def test_default(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/default\")\n            self.assertEqual(response.code, 500)\n            self.assertTrue(b\"500: Internal Server Error\" in response.body)\n\n            response = self.fetch(\"/default?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertTrue(b\"503: Service Unavailable\" in response.body)\n\n            response = self.fetch(\"/default?status=435\")\n            self.assertEqual(response.code, 435)\n            self.assertTrue(b\"435: Unknown\" in response.body)\n\n    def test_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"Exception: ZeroDivisionError\", response.body)\n\n            response = self.fetch(\"/write_error?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertEqual(b\"Status: 503\", response.body)\n\n    def test_failed_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/failed_write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"\", response.body)\n\n\n@wsgi_safe\nclass StaticFileTest(WebTestCase):\n    # The expected MD5 hash of robots.txt, used in tests that call\n    # StaticFileHandler.get_version\n    robots_txt_hash = b\"f71d20196d4caf35b6a670db8c70b03d\"\n    static_dir = os.path.join(os.path.dirname(__file__), 'static')\n\n    def get_handlers(self):\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                with_v = int(self.get_argument('include_version', 1))\n                self.write(self.static_url(path, include_version=with_v))\n\n        class AbsoluteStaticUrlHandler(StaticUrlHandler):\n            include_host = True\n\n        class OverrideStaticUrlHandler(RequestHandler):\n            def get(self, path):\n                do_include = bool(self.get_argument(\"include_host\"))\n                self.include_host = not do_include\n\n                regular_url = self.static_url(path)\n                override_url = self.static_url(path, include_host=do_include)\n                if override_url == regular_url:\n                    return self.write(str(False))\n\n                protocol = self.request.protocol + \"://\"\n                protocol_length = len(protocol)\n                check_regular = regular_url.find(protocol, 0, protocol_length)\n                check_override = override_url.find(protocol, 0, protocol_length)\n\n                if do_include:\n                    result = (check_override == 0 and check_regular == -1)\n                else:\n                    result = (check_override == -1 and check_regular == 0)\n                self.write(str(result))\n\n        return [('/static_url/(.*)', StaticUrlHandler),\n                ('/abs_static_url/(.*)', AbsoluteStaticUrlHandler),\n                ('/override_static_url/(.*)', OverrideStaticUrlHandler),\n                ('/root_static/(.*)', StaticFileHandler, dict(path='/'))]\n\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'))\n\n    def test_static_files(self):\n        response = self.fetch('/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n\n        response = self.fetch('/static/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n        self.assertEqual(response.headers.get(\"Content-Type\"), \"text/plain\")\n\n    def test_static_compressed_files(self):\n        response = self.fetch(\"/static/sample.xml.gz\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/gzip\")\n        response = self.fetch(\"/static/sample.xml.bz2\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/octet-stream\")\n        # make sure the uncompressed file still has the correct type\n        response = self.fetch(\"/static/sample.xml\")\n        self.assertTrue(response.headers.get(\"Content-Type\")\n                        in set((\"text/xml\", \"application/xml\")))\n\n    def test_static_url(self):\n        response = self.fetch(\"/static_url/robots.txt\")\n        self.assertEqual(response.body,\n                         b\"/static/robots.txt?v=\" + self.robots_txt_hash)\n\n    def test_absolute_static_url(self):\n        response = self.fetch(\"/abs_static_url/robots.txt\")\n        self.assertEqual(response.body, (\n            utf8(self.get_url(\"/\")) +\n            b\"static/robots.txt?v=\" +\n            self.robots_txt_hash\n        ))\n\n    def test_relative_version_exclusion(self):\n        response = self.fetch(\"/static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body, b\"/static/robots.txt\")\n\n    def test_absolute_version_exclusion(self):\n        response = self.fetch(\"/abs_static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body,\n                         utf8(self.get_url(\"/\") + \"static/robots.txt\"))\n\n    def test_include_host_override(self):\n        self._trigger_include_host_check(False)\n        self._trigger_include_host_check(True)\n\n    def _trigger_include_host_check(self, include_host):\n        path = \"/override_static_url/robots.txt?include_host=%s\"\n        response = self.fetch(path % int(include_host))\n        self.assertEqual(response.body, utf8(str(True)))\n\n    def get_and_head(self, *args, **kwargs):\n        \"\"\"Performs a GET and HEAD request and returns the GET response.\n\n        Fails if any ``Content-*`` headers returned by the two requests\n        differ.\n        \"\"\"\n        head_response = self.fetch(*args, method=\"HEAD\", **kwargs)\n        get_response = self.fetch(*args, method=\"GET\", **kwargs)\n        content_headers = set()\n        for h in itertools.chain(head_response.headers, get_response.headers):\n            if h.startswith('Content-'):\n                content_headers.add(h)\n        for h in content_headers:\n            self.assertEqual(head_response.headers.get(h),\n                             get_response.headers.get(h),\n                             \"%s differs between GET (%s) and HEAD (%s)\" %\n                             (h, head_response.headers.get(h),\n                              get_response.headers.get(h)))\n        return get_response\n\n    def test_static_304_if_modified_since(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': response1.headers['Last-Modified']})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue('Content-Length' not in response2.headers)\n        self.assertTrue('Last-Modified' not in response2.headers)\n\n    def test_static_304_if_none_match(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-None-Match': response1.headers['Etag']})\n        self.assertEqual(response2.code, 304)\n\n    def test_static_if_modified_since_pre_epoch(self):\n        # On windows, the functions that work with time_t do not accept\n        # negative values, and at least one client (processing.js) seems\n        # to use if-modified-since 1/1/1960 as a cache-busting technique.\n        response = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': 'Fri, 01 Jan 1960 00:00:00 GMT'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_if_modified_since_time_zone(self):\n        # Instead of the value from Last-Modified, make requests with times\n        # chosen just before and after the known modification time\n        # of the file to ensure that the right time zone is being used\n        # when parsing If-Modified-Since.\n        stat = os.stat(relpath('static/robots.txt'))\n\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime - 1)})\n        self.assertEqual(response.code, 200)\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime + 1)})\n        self.assertEqual(response.code, 304)\n\n    def test_static_etag(self):\n        response = self.get_and_head('/static/robots.txt')\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_with_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-9'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b\"User-agent\")\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"10\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 0-9/26\")\n\n    def test_static_with_range_full_file(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-'})\n        # Note: Chrome refuses to play audio if it gets an HTTP 206 in response\n        # to ``Range: bytes=0-`` :(\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_full_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-10000000'})\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_partial_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-10000000'})\n        self.assertEqual(response.code, 206)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()[1:]))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"25\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), \"bytes 1-25/26\")\n\n    def test_static_with_range_end_edge(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=22-'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_with_range_neg_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-4'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_invalid_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'asdf'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_unsatisfiable_range_zero_suffix(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-0'})\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n        self.assertEqual(response.code, 416)\n\n    def test_static_unsatisfiable_range_invalid_start(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=26'})\n        self.assertEqual(response.code, 416)\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n\n    def test_static_head(self):\n        response = self.fetch('/static/robots.txt', method='HEAD')\n        self.assertEqual(response.code, 200)\n        # No body was returned, but we did get the right content length.\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '26')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_head_range(self):\n        response = self.fetch('/static/robots.txt', method='HEAD',\n                              headers={'Range': 'bytes=1-4'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '4')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_range_if_none_match(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-4',\n            'If-None-Match': b'\"' + self.robots_txt_hash + b'\"'})\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.body, b'')\n        self.assertTrue('Content-Length' not in response.headers)\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_404(self):\n        response = self.get_and_head('/static/blarg')\n        self.assertEqual(response.code, 404)\n\n    def test_path_traversal_protection(self):\n        # curl_httpclient processes \"..\" on the client side, so we\n        # must test this with simple_httpclient.\n        self.http_client.close()\n        self.http_client = SimpleAsyncHTTPClient()\n        with ExpectLog(gen_log, \".*not in root static directory\"):\n            response = self.get_and_head('/static/../static_foo.txt')\n        # Attempted path traversal should result in 403, not 200\n        # (which means the check failed and the file was served)\n        # or 404 (which means that the file didn't exist and\n        # is probably a packaging error).\n        self.assertEqual(response.code, 403)\n\n    @unittest.skipIf(os.name != 'posix', 'non-posix OS')\n    def test_root_static_path(self):\n        # Sometimes people set the StaticFileHandler's path to '/'\n        # to disable Tornado's path validation (in conjunction with\n        # their own validation in get_absolute_path). Make sure\n        # that the stricter validation in 4.2.1 doesn't break them.\n        path = os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                            'static/robots.txt')\n        response = self.get_and_head('/root_static' + urllib_parse.quote(path))\n        self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass StaticDefaultFilenameTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return []\n\n    def test_static_default_filename(self):\n        response = self.fetch('/static/dir/', follow_redirects=False)\n        self.assertEqual(response.code, 200)\n        self.assertEqual(b'this is the index\\n', response.body)\n\n    def test_static_default_redirect(self):\n        response = self.fetch('/static/dir', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertTrue(response.headers['Location'].endswith('/static/dir/'))\n\n\n@wsgi_safe\nclass StaticFileWithPathTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return [(\"/foo/(.*)\", StaticFileHandler, {\n            \"path\": relpath(\"templates/\"),\n        })]\n\n    def test_serve(self):\n        response = self.fetch(\"/foo/utf8.html\")\n        self.assertEqual(response.body, b\"H\\xc3\\xa9llo\\n\")\n\n\n@wsgi_safe\nclass CustomStaticFileTest(WebTestCase):\n    def get_handlers(self):\n        class MyStaticFileHandler(StaticFileHandler):\n            @classmethod\n            def make_static_url(cls, settings, path):\n                version_hash = cls.get_version(settings, path)\n                extension_index = path.rindex('.')\n                before_version = path[:extension_index]\n                after_version = path[(extension_index + 1):]\n                return '/static/%s.%s.%s' % (before_version, version_hash,\n                                             after_version)\n\n            def parse_url_path(self, url_path):\n                extension_index = url_path.rindex('.')\n                version_index = url_path.rindex('.', 0, extension_index)\n                return '%s%s' % (url_path[:version_index],\n                                 url_path[extension_index:])\n\n            @classmethod\n            def get_absolute_path(cls, settings, path):\n                return 'CustomStaticFileTest:' + path\n\n            def validate_absolute_path(self, root, absolute_path):\n                return absolute_path\n\n            @classmethod\n            def get_content(self, path, start=None, end=None):\n                assert start is None and end is None\n                if path == 'CustomStaticFileTest:foo.txt':\n                    return b'bar'\n                raise Exception(\"unexpected path %r\" % path)\n\n            def get_content_size(self):\n                if self.absolute_path == 'CustomStaticFileTest:foo.txt':\n                    return 3\n                raise Exception(\"unexpected path %r\" % self.absolute_path)\n\n            def get_modified_time(self):\n                return None\n\n            @classmethod\n            def get_version(cls, settings, path):\n                return \"42\"\n\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                self.write(self.static_url(path))\n\n        self.static_handler_class = MyStaticFileHandler\n\n        return [(\"/static_url/(.*)\", StaticUrlHandler)]\n\n    def get_app_kwargs(self):\n        return dict(static_path=\"dummy\",\n                    static_handler_class=self.static_handler_class)\n\n    def test_serve(self):\n        response = self.fetch(\"/static/foo.42.txt\")\n        self.assertEqual(response.body, b\"bar\")\n\n    def test_static_url(self):\n        with ExpectLog(gen_log, \"Could not open static file\", required=False):\n            response = self.fetch(\"/static_url/foo.txt\")\n            self.assertEqual(response.body, b\"/static/foo.42.txt\")\n\n\n@wsgi_safe\nclass HostMatchingTest(WebTestCase):\n    class Handler(RequestHandler):\n        def initialize(self, reply):\n            self.reply = reply\n\n        def get(self):\n            self.write(self.reply)\n\n    def get_handlers(self):\n        return [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"wildcard\"})]\n\n    def test_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n        self.app.add_handlers(\"www.e.*e.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[3]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"wildcard\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.code, 404)\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[2]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.exe.com'})\n        self.assertEqual(response.body, b\"[3]\")\n\n\n@wsgi_safe\nclass DefaultHostMatchingTest(WebTestCase):\n    def get_handlers(self):\n        return []\n\n    def get_app_kwargs(self):\n        return {'default_host': \"www.example.com\"}\n\n    def test_default_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.test.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={\"X-Real-Ip\": \"127.0.0.1\"})\n        self.assertEqual(response.code, 404)\n\n        self.app.default_host = \"www.test.com\"\n\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.body, b\"[2]\")\n\n\n@wsgi_safe\nclass NamedURLSpecGroupsTest(WebTestCase):\n    def get_handlers(self):\n        class EchoHandler(RequestHandler):\n            def get(self, path):\n                self.write(path)\n\n        return [(\"/str/(?P<path>.*)\", EchoHandler),\n                (u\"/unicode/(?P<path>.*)\", EchoHandler)]\n\n    def test_named_urlspec_groups(self):\n        response = self.fetch(\"/str/foo\")\n        self.assertEqual(response.body, b\"foo\")\n\n        response = self.fetch(\"/unicode/bar\")\n        self.assertEqual(response.body, b\"bar\")\n\n\n@wsgi_safe\nclass ClearHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"h1\", \"foo\")\n            self.set_header(\"h2\", \"bar\")\n            self.clear_header(\"h1\")\n            self.clear_header(\"nonexistent\")\n\n    def test_clear_header(self):\n        response = self.fetch(\"/\")\n        self.assertTrue(\"h1\" not in response.headers)\n        self.assertEqual(response.headers[\"h2\"], \"bar\")\n\n\nclass Header204Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(204)\n            self.finish()\n\n    def test_204_headers(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 204)\n        self.assertNotIn(\"Content-Length\", response.headers)\n        self.assertNotIn(\"Transfer-Encoding\", response.headers)\n\n\n@wsgi_safe\nclass Header304Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"Content-Language\", \"en_US\")\n            self.write(\"hello\")\n\n    def test_304_headers(self):\n        response1 = self.fetch('/')\n        self.assertEqual(response1.headers[\"Content-Length\"], \"5\")\n        self.assertEqual(response1.headers[\"Content-Language\"], \"en_US\")\n\n        response2 = self.fetch('/', headers={\n            'If-None-Match': response1.headers[\"Etag\"]})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue(\"Content-Length\" not in response2.headers)\n        self.assertTrue(\"Content-Language\" not in response2.headers)\n        # Not an entity header, but should not be added to 304s by chunking\n        self.assertTrue(\"Transfer-Encoding\" not in response2.headers)\n\n\n@wsgi_safe\nclass StatusReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            reason = self.request.arguments.get('reason', [])\n            self.set_status(int(self.get_argument('code')),\n                            reason=reason[0] if reason else None)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_status(self):\n        response = self.fetch(\"/?code=304\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Not Modified\")\n        response = self.fetch(\"/?code=304&reason=Foo\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Foo\")\n        response = self.fetch(\"/?code=682&reason=Bar\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Bar\")\n        response = self.fetch(\"/?code=682\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Unknown\")\n\n\n@wsgi_safe\nclass DateHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(\"hello\")\n\n    def test_date_header(self):\n        response = self.fetch('/')\n        header_date = datetime.datetime(\n            *email.utils.parsedate(response.headers['Date'])[:6])\n        self.assertTrue(header_date - datetime.datetime.utcnow() <\n                        datetime.timedelta(seconds=2))\n\n\n@wsgi_safe\nclass RaiseWithReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            raise HTTPError(682, reason=\"Foo\")\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_raise_with_reason(self):\n        response = self.fetch(\"/\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Foo\")\n        self.assertIn(b'682: Foo', response.body)\n\n    def test_httperror_str(self):\n        self.assertEqual(str(HTTPError(682, reason=\"Foo\")), \"HTTP 682: Foo\")\n\n    def test_httperror_str_from_httputil(self):\n        self.assertEqual(str(HTTPError(682)), \"HTTP 682: Unknown\")\n\n\n@wsgi_safe\nclass ErrorHandlerXSRFTest(WebTestCase):\n    def get_handlers(self):\n        # note that if the handlers list is empty we get the default_host\n        # redirect fallback instead of a 404, so test with both an\n        # explicitly defined error handler and an implicit 404.\n        return [('/error', ErrorHandler, dict(status_code=417))]\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def test_error_xsrf(self):\n        response = self.fetch('/error', method='POST', body='')\n        self.assertEqual(response.code, 417)\n\n    def test_404_xsrf(self):\n        response = self.fetch('/404', method='POST', body='')\n        self.assertEqual(response.code, 404)\n\n\n@wsgi_safe\nclass GzipTestCase(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            for v in self.get_arguments('vary'):\n                self.add_header('Vary', v)\n            # Must write at least MIN_LENGTH bytes to activate compression.\n            self.write('hello world' + ('!' * GZipContentEncoding.MIN_LENGTH))\n\n    def get_app_kwargs(self):\n        return dict(\n            gzip=True,\n            static_path=os.path.join(os.path.dirname(__file__), 'static'))\n\n    def assert_compressed(self, response):\n        # simple_httpclient renames the content-encoding header;\n        # curl_httpclient doesn't.\n        self.assertEqual(\n            response.headers.get(\n                'Content-Encoding',\n                response.headers.get('X-Consumed-Content-Encoding')),\n            'gzip')\n\n    def test_gzip(self):\n        response = self.fetch('/')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_static(self):\n        # The streaming responses in StaticFileHandler have subtle\n        # interactions with the gzip output so test this case separately.\n        response = self.fetch('/robots.txt')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_not_requested(self):\n        response = self.fetch('/', use_gzip=False)\n        self.assertNotIn('Content-Encoding', response.headers)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_vary_already_present(self):\n        response = self.fetch('/?vary=Accept-Language')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Accept-Encoding'])\n\n    def test_vary_already_present_multiple(self):\n        # Regression test for https://github.com/tornadoweb/tornado/issues/1670\n        response = self.fetch('/?vary=Accept-Language&vary=Cookie')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Cookie', 'Accept-Encoding'])\n\n\n@wsgi_safe\nclass PathArgsInPrepareTest(WebTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.write(dict(args=self.path_args, kwargs=self.path_kwargs))\n\n        def get(self, path):\n            assert path == 'foo'\n            self.finish()\n\n    def get_handlers(self):\n        return [('/pos/(.*)', self.Handler),\n                ('/kw/(?P<path>.*)', self.Handler)]\n\n    def test_pos(self):\n        response = self.fetch('/pos/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': ['foo'], 'kwargs': {}})\n\n    def test_kw(self):\n        response = self.fetch('/kw/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': [], 'kwargs': {'path': 'foo'}})\n\n\n@wsgi_safe\nclass ClearAllCookiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.clear_all_cookies()\n            self.write('ok')\n\n    def test_clear_all_cookies(self):\n        response = self.fetch('/', headers={'Cookie': 'foo=bar; baz=xyzzy'})\n        set_cookies = sorted(response.headers.get_list('Set-Cookie'))\n        # Python 3.5 sends 'baz=\"\";'; older versions use 'baz=;'\n        self.assertTrue(set_cookies[0].startswith('baz=;') or\n                        set_cookies[0].startswith('baz=\"\";'))\n        self.assertTrue(set_cookies[1].startswith('foo=;') or\n                        set_cookies[1].startswith('foo=\"\";'))\n\n\nclass PermissionError(Exception):\n    pass\n\n\n@wsgi_safe\nclass ExceptionHandlerTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            exc = self.get_argument('exc')\n            if exc == 'http':\n                raise HTTPError(410, \"no longer here\")\n            elif exc == 'zero':\n                1 / 0\n            elif exc == 'permission':\n                raise PermissionError('not allowed')\n\n        def write_error(self, status_code, **kwargs):\n            if 'exc_info' in kwargs:\n                typ, value, tb = kwargs['exc_info']\n                if isinstance(value, PermissionError):\n                    self.set_status(403)\n                    self.write('PermissionError')\n                    return\n            RequestHandler.write_error(self, status_code, **kwargs)\n\n        def log_exception(self, typ, value, tb):\n            if isinstance(value, PermissionError):\n                app_log.warning('custom logging for PermissionError: %s',\n                                value.args[0])\n            else:\n                RequestHandler.log_exception(self, typ, value, tb)\n\n    def test_http_error(self):\n        # HTTPErrors are logged as warnings with no stack trace.\n        # TODO: extend ExpectLog to test this more precisely\n        with ExpectLog(gen_log, '.*no longer here'):\n            response = self.fetch('/?exc=http')\n            self.assertEqual(response.code, 410)\n\n    def test_unknown_error(self):\n        # Unknown errors are logged as errors with a stack trace.\n        with ExpectLog(app_log, 'Uncaught exception'):\n            response = self.fetch('/?exc=zero')\n            self.assertEqual(response.code, 500)\n\n    def test_known_error(self):\n        # log_exception can override logging behavior, and write_error\n        # can override the response.\n        with ExpectLog(app_log,\n                       'custom logging for PermissionError: not allowed'):\n            response = self.fetch('/?exc=permission')\n            self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass BuggyLoggingTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            1 / 0\n\n        def log_exception(self, typ, value, tb):\n            1 / 0\n\n    def test_buggy_log_exception(self):\n        # Something gets logged even though the application's\n        # logger is broken.\n        with ExpectLog(app_log, '.*'):\n            self.fetch('/')\n\n\n@wsgi_safe\nclass UIMethodUIModuleTest(SimpleHandlerTestCase):\n    \"\"\"Test that UI methods and modules are created correctly and\n    associated with the handler.\n    \"\"\"\n    class Handler(RequestHandler):\n        def get(self):\n            self.render('foo.html')\n\n        def value(self):\n            return self.get_argument(\"value\")\n\n    def get_app_kwargs(self):\n        def my_ui_method(handler, x):\n            return \"In my_ui_method(%s) with handler value %s.\" % (\n                x, handler.value())\n\n        class MyModule(UIModule):\n            def render(self, x):\n                return \"In MyModule(%s) with handler value %s.\" % (\n                    x, self.handler.value())\n\n        loader = DictLoader({\n            'foo.html': '{{ my_ui_method(42) }} {% module MyModule(123) %}',\n        })\n        return dict(template_loader=loader,\n                    ui_methods={'my_ui_method': my_ui_method},\n                    ui_modules={'MyModule': MyModule})\n\n    def tearDown(self):\n        super(UIMethodUIModuleTest, self).tearDown()\n        # TODO: fix template loader caching so this isn't necessary.\n        RequestHandler._template_loaders.clear()\n\n    def test_ui_method(self):\n        response = self.fetch('/?value=asdf')\n        self.assertEqual(response.body,\n                         b'In my_ui_method(42) with handler value asdf. '\n                         b'In MyModule(123) with handler value asdf.')\n\n\n@wsgi_safe\nclass GetArgumentErrorTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            try:\n                self.get_argument('foo')\n                self.write({})\n            except MissingArgumentError as e:\n                self.write({'arg_name': e.arg_name,\n                            'log_message': e.log_message})\n\n    def test_catch_error(self):\n        response = self.fetch('/')\n        self.assertEqual(json_decode(response.body),\n                         {'arg_name': 'foo',\n                          'log_message': 'Missing argument foo'})\n\n\nclass MultipleExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        exc_count = 0\n\n        @asynchronous\n        def get(self):\n            from tornado.ioloop import IOLoop\n            IOLoop.current().add_callback(lambda: 1 / 0)\n            IOLoop.current().add_callback(lambda: 1 / 0)\n\n        def log_exception(self, typ, value, tb):\n            MultipleExceptionTest.Handler.exc_count += 1\n\n    def test_multi_exception(self):\n        # This test verifies that multiple exceptions raised into the same\n        # ExceptionStackContext do not generate extraneous log entries\n        # due to \"Cannot send error response after headers written\".\n        # log_exception is called, but it does not proceed to send_error.\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        # Each of our two requests generated two exceptions, we should have\n        # seen at least three of them by now (the fourth may still be\n        # in the queue).\n        self.assertGreater(MultipleExceptionTest.Handler.exc_count, 2)\n\n\n@wsgi_safe\nclass SetLazyPropertiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.current_user = 'Ben'\n            self.locale = locale.get('en_US')\n\n        def get_user_locale(self):\n            raise NotImplementedError()\n\n        def get_current_user(self):\n            raise NotImplementedError()\n\n        def get(self):\n            self.write('Hello %s (%s)' % (self.current_user, self.locale.code))\n\n    def test_set_properties(self):\n        # Ensure that current_user can be assigned to normally for apps\n        # that want to forgo the lazy get_current_user property\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'Hello Ben (en_US)')\n\n\n@wsgi_safe\nclass GetCurrentUserTest(WebTestCase):\n    def get_app_kwargs(self):\n        class WithoutUserModule(UIModule):\n            def render(self):\n                return ''\n\n        class WithUserModule(UIModule):\n            def render(self):\n                return str(self.current_user)\n\n        loader = DictLoader({\n            'without_user.html': '',\n            'with_user.html': '{{ current_user }}',\n            'without_user_module.html': '{% module WithoutUserModule() %}',\n            'with_user_module.html': '{% module WithUserModule() %}',\n        })\n        return dict(template_loader=loader,\n                    ui_modules={'WithUserModule': WithUserModule,\n                                'WithoutUserModule': WithoutUserModule})\n\n    def tearDown(self):\n        super(GetCurrentUserTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        class CurrentUserHandler(RequestHandler):\n            def prepare(self):\n                self.has_loaded_current_user = False\n\n            def get_current_user(self):\n                self.has_loaded_current_user = True\n                return ''\n\n        class WithoutUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('without_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('with_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class CurrentUserModuleHandler(CurrentUserHandler):\n            def get_template_namespace(self):\n                # If RequestHandler.get_template_namespace is called, then\n                # get_current_user is evaluated. Until #820 is fixed, this\n                # is a small hack to circumvent the issue.\n                return self.ui\n\n        class WithoutUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('without_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('with_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        return [('/without_user', WithoutUserHandler),\n                ('/with_user', WithUserHandler),\n                ('/without_user_module', WithoutUserModuleHandler),\n                ('/with_user_module', WithUserModuleHandler)]\n\n    @unittest.skip('needs fix')\n    def test_get_current_user_is_lazy(self):\n        # TODO: Make this test pass. See #820.\n        response = self.fetch('/without_user')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_works(self):\n        response = self.fetch('/with_user')\n        self.assertEqual(response.body, b'True')\n\n    def test_get_current_user_from_ui_module_is_lazy(self):\n        response = self.fetch('/without_user_module')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_from_ui_module_works(self):\n        response = self.fetch('/with_user_module')\n        self.assertEqual(response.body, b'True')\n\n\n@wsgi_safe\nclass UnimplementedHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        pass\n\n    def test_unimplemented_standard_methods(self):\n        for method in ['HEAD', 'GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.code, 405)\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.code, 405)\n\n\nclass UnimplementedNonStandardMethodsTest(SimpleHandlerTestCase):\n    # wsgiref.validate complains about unknown methods in a way that makes\n    # this test not wsgi_safe.\n    class Handler(RequestHandler):\n        def other(self):\n            # Even though this method exists, it won't get called automatically\n            # because it is not in SUPPORTED_METHODS.\n            self.write('other')\n\n    def test_unimplemented_patch(self):\n        # PATCH is recently standardized; Tornado supports it by default\n        # but wsgiref.validate doesn't like it.\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.code, 405)\n\n    def test_unimplemented_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.code, 405)\n\n\n@wsgi_safe\nclass AllHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def method(self):\n            self.write(self.request.method)\n\n        get = delete = options = post = put = method\n\n    def test_standard_methods(self):\n        response = self.fetch('/', method='HEAD')\n        self.assertEqual(response.body, b'')\n        for method in ['GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.body, utf8(method))\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.body, utf8(method))\n\n\nclass PatchMethodTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        SUPPORTED_METHODS = RequestHandler.SUPPORTED_METHODS + ('OTHER',)\n\n        def patch(self):\n            self.write('patch')\n\n        def other(self):\n            self.write('other')\n\n    def test_patch(self):\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.body, b'patch')\n\n    def test_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.body, b'other')\n\n\n@wsgi_safe\nclass FinishInPrepareTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.finish('done')\n\n        def get(self):\n            # It's difficult to assert for certain that a method did not\n            # or will not be called in an asynchronous context, but this\n            # will be logged noisily if it is reached.\n            raise Exception('should not reach this method')\n\n    def test_finish_in_prepare(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'done')\n\n\n@wsgi_safe\nclass Default404Test(WebTestCase):\n    def get_handlers(self):\n        # If there are no handlers at all a default redirect handler gets added.\n        return [('/foo', RequestHandler)]\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body,\n                         b'<html><title>404: Not Found</title>'\n                         b'<body>404: Not Found</body></html>')\n\n\n@wsgi_safe\nclass Custom404Test(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        class Custom404Handler(RequestHandler):\n            def get(self):\n                self.set_status(404)\n                self.write('custom 404 response')\n\n        return dict(default_handler_class=Custom404Handler)\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body, b'custom 404 response')\n\n\n@wsgi_safe\nclass DefaultHandlerArgumentsTest(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        return dict(default_handler_class=ErrorHandler,\n                    default_handler_args=dict(status_code=403))\n\n    def test_403(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass HandlerByNameTest(WebTestCase):\n    def get_handlers(self):\n        # All three are equivalent.\n        return [('/hello1', HelloHandler),\n                ('/hello2', 'tornado.test.web_test.HelloHandler'),\n                url('/hello3', 'tornado.test.web_test.HelloHandler'),\n                ]\n\n    def test_handler_by_name(self):\n        resp = self.fetch('/hello1')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello2')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello3')\n        self.assertEqual(resp.body, b'hello')\n\n\nclass StreamingRequestBodyTest(WebTestCase):\n    def get_handlers(self):\n        @stream_request_body\n        class StreamingBodyHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def prepare(self):\n                self.test.prepared.set_result(None)\n\n            def data_received(self, data):\n                self.test.data.set_result(data)\n\n            def get(self):\n                self.test.finished.set_result(None)\n                self.write({})\n\n        @stream_request_body\n        class EarlyReturnHandler(RequestHandler):\n            def prepare(self):\n                # If we finish the response in prepare, it won't continue to\n                # the (non-existent) data_received.\n                raise HTTPError(401)\n\n        @stream_request_body\n        class CloseDetectionHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def on_connection_close(self):\n                super(CloseDetectionHandler, self).on_connection_close()\n                self.test.close_future.set_result(None)\n\n        return [('/stream_body', StreamingBodyHandler, dict(test=self)),\n                ('/early_return', EarlyReturnHandler),\n                ('/close_detection', CloseDetectionHandler, dict(test=self))]\n\n    def connect(self, url, connection_close):\n        # Use a raw connection so we can control the sending of data.\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        stream = IOStream(s)\n        stream.write(b\"GET \" + url + b\" HTTP/1.1\\r\\n\")\n        if connection_close:\n            stream.write(b\"Connection: close\\r\\n\")\n        stream.write(b\"Transfer-Encoding: chunked\\r\\n\\r\\n\")\n        return stream\n\n    @gen_test\n    def test_streaming_body(self):\n        self.prepared = Future()\n        self.data = Future()\n        self.finished = Future()\n\n        stream = self.connect(b\"/stream_body\", connection_close=True)\n        yield self.prepared\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        # Ensure the first chunk is received before we send the second.\n        data = yield self.data\n        self.assertEqual(data, b\"asdf\")\n        self.data = Future()\n        stream.write(b\"4\\r\\nqwer\\r\\n\")\n        data = yield self.data\n        self.assertEquals(data, b\"qwer\")\n        stream.write(b\"0\\r\\n\")\n        yield self.finished\n        data = yield gen.Task(stream.read_until_close)\n        # This would ideally use an HTTP1Connection to read the response.\n        self.assertTrue(data.endswith(b\"{}\"))\n        stream.close()\n\n    @gen_test\n    def test_early_return(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_early_return_with_data(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_close_during_upload(self):\n        self.close_future = Future()\n        stream = self.connect(b\"/close_detection\", connection_close=False)\n        stream.close()\n        yield self.close_future\n\n\n# Each method in this handler returns a yieldable object and yields to the\n# IOLoop so the future is not immediately ready.  Ensure that the\n# yieldables are respected and no method is called before the previous\n# one has completed.\n@stream_request_body\nclass BaseFlowControlHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n        self.method = None\n        self.methods = []\n\n    @contextlib.contextmanager\n    def in_method(self, method):\n        if self.method is not None:\n            self.test.fail(\"entered method %s while in %s\" %\n                           (method, self.method))\n        self.method = method\n        self.methods.append(method)\n        try:\n            yield\n        finally:\n            self.method = None\n\n    @gen.coroutine\n    def prepare(self):\n        # Note that asynchronous prepare() does not block data_received,\n        # so we don't use in_method here.\n        self.methods.append('prepare')\n        yield gen.Task(IOLoop.current().add_callback)\n\n    @gen.coroutine\n    def post(self):\n        with self.in_method('post'):\n            yield gen.Task(IOLoop.current().add_callback)\n        self.write(dict(methods=self.methods))\n\n\nclass BaseStreamingRequestFlowControlTest(object):\n    def get_httpserver_options(self):\n        # Use a small chunk size so flow control is relevant even though\n        # all the data arrives at once.\n        return dict(chunk_size=10, decompress_request=True)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't support body_producer.\n        return SimpleAsyncHTTPClient()\n\n    # Test all the slightly different code paths for fixed, chunked, etc bodies.\n    def test_flow_control_fixed_body(self):\n        response = self.fetch('/', body='abcdefghijklmnopqrstuvwxyz',\n                              method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_chunked_body(self):\n        chunks = [b'abcd', b'efgh', b'ijkl']\n\n        @gen.coroutine\n        def body_producer(write):\n            for i in chunks:\n                yield write(i)\n        response = self.fetch('/', body_producer=body_producer, method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_compressed_body(self):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(b'abcdefghijklmnopqrstuvwxyz')\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        response = self.fetch('/', body=compressed_body, method='POST',\n                              headers={'Content-Encoding': 'gzip'})\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n\nclass DecoratedStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class DecoratedFlowControlHandler(BaseFlowControlHandler):\n            @gen.coroutine\n            def data_received(self, data):\n                with self.in_method('data_received'):\n                    yield gen.Task(IOLoop.current().add_callback)\n        return [('/', DecoratedFlowControlHandler, dict(test=self))]\n\n\n@skipBefore35\nclass NativeStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class NativeFlowControlHandler(BaseFlowControlHandler):\n            data_received = exec_test(globals(), locals(), \"\"\"\n            async def data_received(self, data):\n                with self.in_method('data_received'):\n                    await gen.Task(IOLoop.current().add_callback)\n            \"\"\")[\"data_received\"]\n        return [('/', NativeFlowControlHandler, dict(test=self))]\n\n\n@wsgi_safe\nclass IncorrectContentLengthTest(SimpleHandlerTestCase):\n    def get_handlers(self):\n        test = self\n        self.server_error = None\n\n        # Manually set a content-length that doesn't match the actual content.\n        class TooHigh(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"42\")\n                try:\n                    self.finish(\"ok\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        class TooLow(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"2\")\n                try:\n                    self.finish(\"hello\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        return [('/high', TooHigh),\n                ('/low', TooLow)]\n\n    def test_content_length_too_high(self):\n        # When the content-length is too high, the connection is simply\n        # closed without completing the response.  An error is logged on\n        # the server.\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/high\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write 40 bytes less than Content-Length\")\n\n    def test_content_length_too_low(self):\n        # When the content-length is too low, the connection is closed\n        # without writing the last chunk, so the client never sees the request\n        # complete (which would be a framing error).\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/low\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write more data than Content-Length\")\n\n\nclass ClientCloseTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            if self.request.version.startswith('HTTP/1'):\n                # Simulate a connection closed by the client during\n                # request processing.  The client will see an error, but the\n                # server should respond gracefully (without logging errors\n                # because we were unable to write out as many bytes as\n                # Content-Length said we would)\n                self.request.connection.stream.close()\n                self.write('hello')\n            else:\n                # TODO: add a HTTP2-compatible version of this test.\n                self.write('requires HTTP/1.x')\n\n    def test_client_close(self):\n        response = self.fetch('/')\n        if response.body == b'requires HTTP/1.x':\n            self.skipTest('requires HTTP/1.x')\n        self.assertEqual(response.code, 599)\n\n\nclass SignedValueTest(unittest.TestCase):\n    SECRET = \"It's a secret to everybody\"\n    SECRET_DICT = {0: \"asdfbasdf\", 1: \"12312312\", 2: \"2342342\"}\n\n    def past(self):\n        return self.present() - 86400 * 32\n\n    def present(self):\n        return 1300000000\n\n    def test_known_values(self):\n        signed_v1 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=1, clock=self.present)\n        self.assertEqual(\n            signed_v1,\n            b\"dmFsdWU=|1300000000|31c934969f53e48164c50768b40cbd7e2daaaa4f\")\n\n        signed_v2 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=2, clock=self.present)\n        self.assertEqual(\n            signed_v2,\n            b\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n            b\"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\")\n\n        signed_default = create_signed_value(SignedValueTest.SECRET,\n                                             \"key\", \"value\", clock=self.present)\n        self.assertEqual(signed_default, signed_v2)\n\n        decoded_v1 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v1, min_version=1,\n                                         clock=self.present)\n        self.assertEqual(decoded_v1, b\"value\")\n\n        decoded_v2 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v2, min_version=2,\n                                         clock=self.present)\n        self.assertEqual(decoded_v2, b\"value\")\n\n    def test_name_swap(self):\n        signed1 = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                      clock=self.present)\n        signed2 = create_signed_value(SignedValueTest.SECRET, \"key2\", \"value\",\n                                      clock=self.present)\n        # Try decoding each string with the other's \"name\"\n        decoded1 = decode_signed_value(SignedValueTest.SECRET, \"key2\", signed1,\n                                       clock=self.present)\n        self.assertIs(decoded1, None)\n        decoded2 = decode_signed_value(SignedValueTest.SECRET, \"key1\", signed2,\n                                       clock=self.present)\n        self.assertIs(decoded2, None)\n\n    def test_expired(self):\n        signed = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                     clock=self.past)\n        decoded_past = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                           signed, clock=self.past)\n        self.assertEqual(decoded_past, b\"value\")\n        decoded_present = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                              signed, clock=self.present)\n        self.assertIs(decoded_present, None)\n\n    def test_payload_tampering(self):\n        # These cookies are variants of the one in test_known_values.\n        sig = \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"\n\n        def validate(prefix):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # Change key version\n        self.assertFalse(validate(\"2|1:1|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too short)\n        self.assertFalse(validate(\"2|1:0|10:130000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too long)\n        self.assertFalse(validate(\"2|1:0|10:1300000000|3:keey|8:dmFsdWU=|\"))\n\n    def test_signature_tampering(self):\n        prefix = \"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n\n        def validate(sig):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # All zeros\n        self.assertFalse(validate(\"0\" * 32))\n        # Change one character\n        self.assertFalse(validate(\n            \"4d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # Change another character\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e153\"))\n        # Truncate\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e15\"))\n        # Lengthen\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e1538\"))\n\n    def test_non_ascii(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET, \"key\", value,\n                                     clock=self.present)\n        decoded = decode_signed_value(SignedValueTest.SECRET, \"key\", signed,\n                                      clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_non_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_invalid_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        newkeys = SignedValueTest.SECRET_DICT.copy()\n        newkeys.pop(0)\n        decoded = decode_signed_value(newkeys,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(None, decoded)\n\n    def test_key_version_retrieval(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        key_version = get_signature_key_version(signed)\n        self.assertEqual(1, key_version)\n\n\n@wsgi_safe\nclass XSRFTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            version = int(self.get_argument(\"version\", \"2\"))\n            # This would be a bad idea in a real app, but in this test\n            # it's fine.\n            self.settings[\"xsrf_cookie_version\"] = version\n            self.write(self.xsrf_token)\n\n        def post(self):\n            self.write(\"ok\")\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def setUp(self):\n        super(XSRFTest, self).setUp()\n        self.xsrf_token = self.get_token()\n\n    def get_token(self, old_token=None, version=None):\n        if old_token is not None:\n            headers = self.cookie_headers(old_token)\n        else:\n            headers = None\n        response = self.fetch(\n            \"/\" if version is None else (\"/?version=%d\" % version),\n            headers=headers)\n        response.rethrow()\n        return native_str(response.body)\n\n    def cookie_headers(self, token=None):\n        if token is None:\n            token = self.xsrf_token\n        return {\"Cookie\": \"_xsrf=\" + token}\n\n    def test_xsrf_fail_no_token(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\"/\", method=\"POST\", body=b\"\")\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_body_no_cookie(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_argument_invalid_format(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument has invalid format\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(),\n                body=urllib_parse.urlencode(dict(_xsrf='3|')))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_invalid_format(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(token='3|'),\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_no_body(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\n                \"/\", method=\"POST\", body=b\"\",\n                headers=self.cookie_headers())\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_success_short_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='deadbeef')),\n            headers=self.cookie_headers(token='deadbeef'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_non_hex_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='xoxo')),\n            headers=self.cookie_headers(token='xoxo'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_post_body(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_query_string(self):\n        response = self.fetch(\n            \"/?\" + urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            method=\"POST\", body=b\"\",\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_header(self):\n        response = self.fetch(\"/\", method=\"POST\", body=b\"\",\n                              headers=dict({\"X-Xsrftoken\": self.xsrf_token},  # type: ignore\n                                           **self.cookie_headers()))\n        self.assertEqual(response.code, 200)\n\n    def test_distinct_tokens(self):\n        # Every request gets a distinct token.\n        NUM_TOKENS = 10\n        tokens = set()\n        for i in range(NUM_TOKENS):\n            tokens.add(self.get_token())\n        self.assertEqual(len(tokens), NUM_TOKENS)\n\n    def test_cross_user(self):\n        token2 = self.get_token()\n        # Each token can be used to authenticate its own request.\n        for token in (self.xsrf_token, token2):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        # Sending one in the cookie and the other in the body is not allowed.\n        for cookie_token, body_token in ((self.xsrf_token, token2),\n                                         (token2, self.xsrf_token)):\n            with ExpectLog(gen_log, '.*XSRF cookie does not match POST'):\n                response = self.fetch(\n                    \"/\", method=\"POST\",\n                    body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                    headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 403)\n\n    def test_refresh_token(self):\n        token = self.xsrf_token\n        tokens_seen = set([token])\n        # A user's token is stable over time.  Refreshing the page in one tab\n        # might update the cookie while an older tab still has the old cookie\n        # in its DOM.  Simulate this scenario by passing a constant token\n        # in the body and re-querying for the token.\n        for i in range(5):\n            token = self.get_token(token)\n            # Tokens are encoded uniquely each time\n            tokens_seen.add(token)\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        self.assertEqual(len(tokens_seen), 6)\n\n    def test_versioning(self):\n        # Version 1 still produces distinct tokens per request.\n        self.assertNotEqual(self.get_token(version=1),\n                            self.get_token(version=1))\n\n        # Refreshed v1 tokens are all identical.\n        v1_token = self.get_token(version=1)\n        for i in range(5):\n            self.assertEqual(self.get_token(v1_token, version=1), v1_token)\n\n        # Upgrade to a v2 version of the same token\n        v2_token = self.get_token(v1_token)\n        self.assertNotEqual(v1_token, v2_token)\n        # Each v1 token can map to many v2 tokens.\n        self.assertNotEqual(v2_token, self.get_token(v1_token))\n\n        # The tokens are cross-compatible.\n        for cookie_token, body_token in ((v1_token, v2_token),\n                                         (v2_token, v1_token)):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass XSRFCookieKwargsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(self.xsrf_token)\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True,\n                    xsrf_cookie_kwargs=dict(httponly=True))\n\n    def test_xsrf_httponly(self):\n        response = self.fetch(\"/\")\n        self.assertIn('httponly;', response.headers['Set-Cookie'].lower())\n\n\n@wsgi_safe\nclass FinishExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(401)\n            self.set_header('WWW-Authenticate', 'Basic realm=\"something\"')\n            if self.get_argument('finish_value', ''):\n                raise Finish('authentication required')\n            else:\n                self.write('authentication required')\n                raise Finish()\n\n    def test_finish_exception(self):\n        for u in ['/', '/?finish_value=1']:\n            response = self.fetch(u)\n            self.assertEqual(response.code, 401)\n            self.assertEqual('Basic realm=\"something\"',\n                             response.headers.get('WWW-Authenticate'))\n            self.assertEqual(b'authentication required', response.body)\n\n\n@wsgi_safe\nclass DecoratorTest(WebTestCase):\n    def get_handlers(self):\n        class RemoveSlashHandler(RequestHandler):\n            @removeslash\n            def get(self):\n                pass\n\n        class AddSlashHandler(RequestHandler):\n            @addslash\n            def get(self):\n                pass\n\n        return [(\"/removeslash/\", RemoveSlashHandler),\n                (\"/addslash\", AddSlashHandler),\n                ]\n\n    def test_removeslash(self):\n        response = self.fetch(\"/removeslash/\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash\")\n\n        response = self.fetch(\"/removeslash/?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash?foo=bar\")\n\n    def test_addslash(self):\n        response = self.fetch(\"/addslash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/\")\n\n        response = self.fetch(\"/addslash?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/?foo=bar\")\n\n\n@wsgi_safe\nclass CacheTest(WebTestCase):\n    def get_handlers(self):\n        class EtagHandler(RequestHandler):\n            def get(self, computed_etag):\n                self.write(computed_etag)\n\n            def compute_etag(self):\n                return self._write_buffer[0]\n\n        return [\n            ('/etag/(.*)', EtagHandler)\n        ]\n\n    def test_wildcard_etag(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '*'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_strong_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_weak_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_weak_etag_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy3\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def _test_etag(self, computed_etag, etags, status_code):\n        response = self.fetch(\n            '/etag/' + computed_etag,\n            headers={'If-None-Match': etags}\n        )\n        self.assertEqual(response.code, status_code)\n\n\n@wsgi_safe\nclass RequestSummaryTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            # remote_ip is optional, although it's set by\n            # both HTTPServer and WSGIAdapter.\n            # Clobber it to make sure it doesn't break logging.\n            self.request.remote_ip = None\n            self.finish(self._request_summary())\n\n    def test_missing_remote_ip(self):\n        resp = self.fetch(\"/\")\n        self.assertEqual(resp.body, b\"GET / (None)\")\n\n\nclass HTTPErrorTest(unittest.TestCase):\n    def test_copy(self):\n        e = HTTPError(403, reason=\"Go away\")\n        e2 = copy.copy(e)\n        self.assertIsNot(e, e2)\n        self.assertEqual(e.status_code, e2.status_code)\n        self.assertEqual(e.reason, e2.reason)\n\n\nclass ApplicationTest(AsyncTestCase):\n    def test_listen(self):\n        app = Application([])\n        server = app.listen(0, address='127.0.0.1')\n        server.stop()\n\n\nclass URLSpecReverseTest(unittest.TestCase):\n    def test_reverse(self):\n        self.assertEqual('/favicon.ico', url(r'/favicon\\.ico', None).reverse())\n        self.assertEqual('/favicon.ico', url(r'^/favicon\\.ico$', None).reverse())\n\n    def test_non_reversible(self):\n        # URLSpecs are non-reversible if they include non-constant\n        # regex features outside capturing groups. Currently, this is\n        # only strictly enforced for backslash-escaped character\n        # classes.\n        paths = [\n            r'^/api/v\\d+/foo/(\\w+)$',\n        ]\n        for path in paths:\n            # A URLSpec can still be created even if it cannot be reversed.\n            url_spec = url(path, None)\n            try:\n                result = url_spec.reverse()\n                self.fail(\"did not get expected exception when reversing %s. \"\n                          \"result: %s\" % (path, result))\n            except ValueError:\n                pass\n\n    def test_reverse_arguments(self):\n        self.assertEqual('/api/v1/foo/bar',\n                         url(r'^/api/v1/foo/(\\w+)$', None).reverse('bar'))\n\n\nclass RedirectHandlerTest(WebTestCase):\n    def get_handlers(self):\n        return [\n            ('/src', WebRedirectHandler, {'url': '/dst'}),\n            ('/src2', WebRedirectHandler, {'url': '/dst2?foo=bar'}),\n            (r'/(.*?)/(.*?)/(.*)', WebRedirectHandler, {'url': '/{1}/{0}/{2}'})]\n\n    def test_basic_redirect(self):\n        response = self.fetch('/src', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst')\n\n    def test_redirect_with_argument(self):\n        response = self.fetch('/src?foo=bar', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst?foo=bar')\n\n    def test_redirect_with_appending_argument(self):\n        response = self.fetch('/src2?foo2=bar2', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst2?foo=bar&foo2=bar2')\n\n    def test_redirect_pattern(self):\n        response = self.fetch('/a/b/c', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/b/a/c')\n",
            "header": {
                "file": {
                    "path": "tornado/test/web_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "7c33fd90",
                "new_commit_hash": "7e3ac7c2",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/web_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/web_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 356,
                            "length": 7
                        },
                        "new_range": {
                            "start": 356,
                            "length": 7
                        },
                        "section": "class AuthRedirectTest(WebTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        response = self.wait()",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(response.code, 302)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertTrue(re.match(",
                                "type": "context"
                            },
                            {
                                "content": "            'http://example.com/login\\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',",
                                "type": "deleted"
                            },
                            {
                                "content": "            'http://example.com/login\\?next=http%3A%2F%2F127.0.0.1%3A[0-9]+%2Fabsolute',",
                                "type": "added"
                            },
                            {
                                "content": "            response.headers['Location']), response.headers['Location'])",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/web_test.py",
                            "type": "method",
                            "name": "AuthRedirectTest.test_absolute_auth_redirect",
                            "content": "class AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 353,
                            "end_lineno": 360,
                            "parent": {
                                "file_name": "tornado/test/web_test.py",
                                "type": "class",
                                "name": "AuthRedirectTest",
                                "content": "class AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 339,
                                "end_lineno": 360,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/web_test.py",
                            "type": "class",
                            "name": "AuthRedirectTest",
                            "content": "class AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 339,
                            "end_lineno": 360,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#!/usr/bin/env python\n\"\"\"Support classes for automated testing.\n\n* `AsyncTestCase` and `AsyncHTTPTestCase`:  Subclasses of unittest.TestCase\n  with additional support for testing asynchronous (`.IOLoop`-based) code.\n\n* `ExpectLog`: Make test logs less spammy.\n\n* `main()`: A simple test runner (wrapper around unittest.main()) with support\n  for the tornado.autoreload module to rerun the tests when code changes.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\ntry:\n    from tornado import gen\n    from tornado.httpclient import AsyncHTTPClient\n    from tornado.httpserver import HTTPServer\n    from tornado.simple_httpclient import SimpleAsyncHTTPClient\n    from tornado.ioloop import IOLoop, TimeoutError\n    from tornado import netutil\n    from tornado.process import Subprocess\nexcept ImportError:\n    # These modules are not importable on app engine.  Parts of this module\n    # won't work, but e.g. main() will.\n    AsyncHTTPClient = None  # type: ignore\n    gen = None  # type: ignore\n    HTTPServer = None  # type: ignore\n    IOLoop = None  # type: ignore\n    netutil = None  # type: ignore\n    SimpleAsyncHTTPClient = None  # type: ignore\n    Subprocess = None  # type: ignore\nfrom tornado.log import gen_log, app_log\nfrom tornado.stack_context import ExceptionStackContext\nfrom tornado.util import raise_exc_info, basestring_type, PY3\nimport functools\nimport inspect\nimport logging\nimport os\nimport re\nimport signal\nimport socket\nimport sys\n\nif PY3:\n    from io import StringIO\nelse:\n    from cStringIO import StringIO\n\ntry:\n    from collections.abc import Generator as GeneratorType  # type: ignore\nexcept ImportError:\n    from types import GeneratorType  # type: ignore\n\nif sys.version_info >= (3, 5):\n    iscoroutine = inspect.iscoroutine  # type: ignore\n    iscoroutinefunction = inspect.iscoroutinefunction  # type: ignore\nelse:\n    iscoroutine = iscoroutinefunction = lambda f: False\n\n# Tornado's own test suite requires the updated unittest module\n# (either py27+ or unittest2) so tornado.test.util enforces\n# this requirement, but for other users of tornado.testing we want\n# to allow the older version if unitest2 is not available.\nif PY3:\n    # On python 3, mixing unittest2 and unittest (including doctest)\n    # doesn't seem to work, so always use unittest.\n    import unittest\nelse:\n    # On python 2, prefer unittest2 when available.\n    try:\n        import unittest2 as unittest  # type: ignore\n    except ImportError:\n        import unittest  # type: ignore\n\n\ndef bind_unused_port(reuse_port=False):\n    \"\"\"Binds a server socket to an available port on localhost.\n\n    Returns a tuple (socket, port).\n\n    .. versionchanged:: 4.4\n       Always binds to ``127.0.0.1`` without resolving the name\n       ``localhost``.\n    \"\"\"\n    sock = netutil.bind_sockets(None, '127.0.0.1', family=socket.AF_INET,\n                                reuse_port=reuse_port)[0]\n    port = sock.getsockname()[1]\n    return sock, port\n\n\ndef get_async_test_timeout():\n    \"\"\"Get the global timeout setting for async tests.\n\n    Returns a float, the timeout in seconds.\n\n    .. versionadded:: 3.1\n    \"\"\"\n    try:\n        return float(os.environ.get('ASYNC_TEST_TIMEOUT'))\n    except (ValueError, TypeError):\n        return 5\n\n\nclass _TestMethodWrapper(object):\n    \"\"\"Wraps a test method to raise an error if it returns a value.\n\n    This is mainly used to detect undecorated generators (if a test\n    method yields it must use a decorator to consume the generator),\n    but will also detect other kinds of return values (these are not\n    necessarily errors, but we alert anyway since there is no good\n    reason to return a value from a test).\n    \"\"\"\n    def __init__(self, orig_method):\n        self.orig_method = orig_method\n\n    def __call__(self, *args, **kwargs):\n        result = self.orig_method(*args, **kwargs)\n        if isinstance(result, GeneratorType) or iscoroutine(result):\n            raise TypeError(\"Generator and coroutine test methods should be\"\n                            \" decorated with tornado.testing.gen_test\")\n        elif result is not None:\n            raise ValueError(\"Return value from test method ignored: %r\" %\n                             result)\n\n    def __getattr__(self, name):\n        \"\"\"Proxy all unknown attributes to the original method.\n\n        This is important for some of the decorators in the `unittest`\n        module, such as `unittest.skipIf`.\n        \"\"\"\n        return getattr(self.orig_method, name)\n\n\nclass AsyncTestCase(unittest.TestCase):\n    \"\"\"`~unittest.TestCase` subclass for testing `.IOLoop`-based\n    asynchronous code.\n\n    The unittest framework is synchronous, so the test must be\n    complete by the time the test method returns.  This means that\n    asynchronous code cannot be used in quite the same way as usual.\n    To write test functions that use the same ``yield``-based patterns\n    used with the `tornado.gen` module, decorate your test methods\n    with `tornado.testing.gen_test` instead of\n    `tornado.gen.coroutine`.  This class also provides the `stop()`\n    and `wait()` methods for a more manual style of testing.  The test\n    method itself must call ``self.wait()``, and asynchronous\n    callbacks should call ``self.stop()`` to signal completion.\n\n    By default, a new `.IOLoop` is constructed for each test and is available\n    as ``self.io_loop``.  If the code being tested requires a\n    global `.IOLoop`, subclasses should override `get_new_ioloop` to return it.\n\n    The `.IOLoop`'s ``start`` and ``stop`` methods should not be\n    called directly.  Instead, use `self.stop <stop>` and `self.wait\n    <wait>`.  Arguments passed to ``self.stop`` are returned from\n    ``self.wait``.  It is possible to have multiple ``wait``/``stop``\n    cycles in the same test.\n\n    Example::\n\n        # This test uses coroutine style.\n        class MyTestCase(AsyncTestCase):\n            @tornado.testing.gen_test\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                response = yield client.fetch(\"http://www.tornadoweb.org\")\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses argument passing between self.stop and self.wait.\n        class MyTestCase2(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.stop)\n                response = self.wait()\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses an explicit callback-based style.\n        class MyTestCase3(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.handle_fetch)\n                self.wait()\n\n            def handle_fetch(self, response):\n                # Test contents of response (failures and exceptions here\n                # will cause self.wait() to throw an exception and end the\n                # test).\n                # Exceptions thrown here are magically propagated to\n                # self.wait() in test_http_fetch() via stack_context.\n                self.assertIn(\"FriendFeed\", response.body)\n                self.stop()\n    \"\"\"\n    def __init__(self, methodName='runTest'):\n        super(AsyncTestCase, self).__init__(methodName)\n        self.__stopped = False\n        self.__running = False\n        self.__failure = None\n        self.__stop_args = None\n        self.__timeout = None\n\n        # It's easy to forget the @gen_test decorator, but if you do\n        # the test will silently be ignored because nothing will consume\n        # the generator.  Replace the test method with a wrapper that will\n        # make sure it's not an undecorated generator.\n        setattr(self, methodName, _TestMethodWrapper(getattr(self, methodName)))\n\n    def setUp(self):\n        super(AsyncTestCase, self).setUp()\n        self.io_loop = self.get_new_ioloop()\n        self.io_loop.make_current()\n\n    def tearDown(self):\n        # Clean up Subprocess, so it can be used again with a new ioloop.\n        Subprocess.uninitialize()\n        self.io_loop.clear_current()\n        # Try to clean up any file descriptors left open in the ioloop.\n        # This avoids leaks, especially when tests are run repeatedly\n        # in the same process with autoreload (because curl does not\n        # set FD_CLOEXEC on its file descriptors)\n        self.io_loop.close(all_fds=True)\n        super(AsyncTestCase, self).tearDown()\n        # In case an exception escaped or the StackContext caught an exception\n        # when there wasn't a wait() to re-raise it, do so here.\n        # This is our last chance to raise an exception in a way that the\n        # unittest machinery understands.\n        self.__rethrow()\n\n    def get_new_ioloop(self):\n        \"\"\"Creates a new `.IOLoop` for this test.  May be overridden in\n        subclasses for tests that require a specific `.IOLoop` (usually\n        the singleton `.IOLoop.instance()`).\n        \"\"\"\n        return IOLoop()\n\n    def _handle_exception(self, typ, value, tb):\n        if self.__failure is None:\n            self.__failure = (typ, value, tb)\n        else:\n            app_log.error(\"multiple unhandled exceptions in test\",\n                          exc_info=(typ, value, tb))\n        self.stop()\n        return True\n\n    def __rethrow(self):\n        if self.__failure is not None:\n            failure = self.__failure\n            self.__failure = None\n            raise_exc_info(failure)\n\n    def run(self, result=None):\n        with ExceptionStackContext(self._handle_exception):\n            super(AsyncTestCase, self).run(result)\n        # As a last resort, if an exception escaped super.run() and wasn't\n        # re-raised in tearDown, raise it here.  This will cause the\n        # unittest run to fail messily, but that's better than silently\n        # ignoring an error.\n        self.__rethrow()\n\n    def stop(self, _arg=None, **kwargs):\n        \"\"\"Stops the `.IOLoop`, causing one pending (or future) call to `wait()`\n        to return.\n\n        Keyword arguments or a single positional argument passed to `stop()` are\n        saved and will be returned by `wait()`.\n        \"\"\"\n        assert _arg is None or not kwargs\n        self.__stop_args = kwargs or _arg\n        if self.__running:\n            self.io_loop.stop()\n            self.__running = False\n        self.__stopped = True\n\n    def wait(self, condition=None, timeout=None):\n        \"\"\"Runs the `.IOLoop` until stop is called or timeout has passed.\n\n        In the event of a timeout, an exception will be thrown. The\n        default timeout is 5 seconds; it may be overridden with a\n        ``timeout`` keyword argument or globally with the\n        ``ASYNC_TEST_TIMEOUT`` environment variable.\n\n        If ``condition`` is not None, the `.IOLoop` will be restarted\n        after `stop()` until ``condition()`` returns true.\n\n        .. versionchanged:: 3.1\n           Added the ``ASYNC_TEST_TIMEOUT`` environment variable.\n        \"\"\"\n        if timeout is None:\n            timeout = get_async_test_timeout()\n\n        if not self.__stopped:\n            if timeout:\n                def timeout_func():\n                    try:\n                        raise self.failureException(\n                            'Async operation timed out after %s seconds' %\n                            timeout)\n                    except Exception:\n                        self.__failure = sys.exc_info()\n                    self.stop()\n                self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func)\n            while True:\n                self.__running = True\n                self.io_loop.start()\n                if (self.__failure is not None or\n                        condition is None or condition()):\n                    break\n            if self.__timeout is not None:\n                self.io_loop.remove_timeout(self.__timeout)\n                self.__timeout = None\n        assert self.__stopped\n        self.__stopped = False\n        self.__rethrow()\n        result = self.__stop_args\n        self.__stop_args = None\n        return result\n\n\nclass AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://localhost:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()\n\n\nclass AsyncHTTPSTestCase(AsyncHTTPTestCase):\n    \"\"\"A test case that starts an HTTPS server.\n\n    Interface is generally the same as `AsyncHTTPTestCase`.\n    \"\"\"\n    def get_http_client(self):\n        return AsyncHTTPClient(force_instance=True,\n                               defaults=dict(validate_cert=False))\n\n    def get_httpserver_options(self):\n        return dict(ssl_options=self.get_ssl_options())\n\n    def get_ssl_options(self):\n        \"\"\"May be overridden by subclasses to select SSL options.\n\n        By default includes a self-signed testing certificate.\n        \"\"\"\n        # Testing keys were generated with:\n        # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509\n        module_dir = os.path.dirname(__file__)\n        return dict(\n            certfile=os.path.join(module_dir, 'test', 'test.crt'),\n            keyfile=os.path.join(module_dir, 'test', 'test.key'))\n\n    def get_protocol(self):\n        return 'https'\n\n\ndef gen_test(func=None, timeout=None):\n    \"\"\"Testing equivalent of ``@gen.coroutine``, to be applied to test methods.\n\n    ``@gen.coroutine`` cannot be used on tests because the `.IOLoop` is not\n    already running.  ``@gen_test`` should be applied to test methods\n    on subclasses of `AsyncTestCase`.\n\n    Example::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test\n            def test_something(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    By default, ``@gen_test`` times out after 5 seconds. The timeout may be\n    overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable,\n    or for each test with the ``timeout`` keyword argument::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test(timeout=10)\n            def test_something_slow(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`,\n    `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield\n    self.http_client.fetch(self.get_url())`` as shown above instead.\n\n    .. versionadded:: 3.1\n       The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment\n       variable.\n\n    .. versionchanged:: 4.0\n       The wrapper now passes along ``*args, **kwargs`` so it can be used\n       on functions with arguments.\n\n    \"\"\"\n    if timeout is None:\n        timeout = get_async_test_timeout()\n\n    def wrap(f):\n        # Stack up several decorators to allow us to access the generator\n        # object itself.  In the innermost wrapper, we capture the generator\n        # and save it in an attribute of self.  Next, we run the wrapped\n        # function through @gen.coroutine.  Finally, the coroutine is\n        # wrapped again to make it synchronous with run_sync.\n        #\n        # This is a good case study arguing for either some sort of\n        # extensibility in the gen decorators or cancellation support.\n        @functools.wraps(f)\n        def pre_coroutine(self, *args, **kwargs):\n            result = f(self, *args, **kwargs)\n            if isinstance(result, GeneratorType) or iscoroutine(result):\n                self._test_generator = result\n            else:\n                self._test_generator = None\n            return result\n\n        if iscoroutinefunction(f):\n            coro = pre_coroutine\n        else:\n            coro = gen.coroutine(pre_coroutine)\n\n        @functools.wraps(coro)\n        def post_coroutine(self, *args, **kwargs):\n            try:\n                return self.io_loop.run_sync(\n                    functools.partial(coro, self, *args, **kwargs),\n                    timeout=timeout)\n            except TimeoutError as e:\n                # run_sync raises an error with an unhelpful traceback.\n                # Throw it back into the generator or coroutine so the stack\n                # trace is replaced by the point where the test is stopped.\n                self._test_generator.throw(e)\n                # In case the test contains an overly broad except clause,\n                # we may get back here.  In this case re-raise the original\n                # exception, which is better than nothing.\n                raise\n        return post_coroutine\n\n    if func is not None:\n        # Used like:\n        #     @gen_test\n        #     def f(self):\n        #         pass\n        return wrap(func)\n    else:\n        # Used like @gen_test(timeout=10)\n        return wrap\n\n\n# Without this attribute, nosetests will try to run gen_test as a test\n# anywhere it is imported.\ngen_test.__test__ = False  # type: ignore\n\n\nclass ExpectLog(logging.Filter):\n    \"\"\"Context manager to capture and suppress expected log output.\n\n    Useful to make tests of error conditions less noisy, while still\n    leaving unexpected log entries visible.  *Not thread safe.*\n\n    The attribute ``logged_stack`` is set to true if any exception\n    stack trace was logged.\n\n    Usage::\n\n        with ExpectLog('tornado.application', \"Uncaught exception\"):\n            error_response = self.fetch(\"/some_page\")\n\n    .. versionchanged:: 4.3\n       Added the ``logged_stack`` attribute.\n    \"\"\"\n    def __init__(self, logger, regex, required=True):\n        \"\"\"Constructs an ExpectLog context manager.\n\n        :param logger: Logger object (or name of logger) to watch.  Pass\n            an empty string to watch the root logger.\n        :param regex: Regular expression to match.  Any log entries on\n            the specified logger that match this regex will be suppressed.\n        :param required: If true, an exception will be raised if the end of\n            the ``with`` statement is reached without matching any log entries.\n        \"\"\"\n        if isinstance(logger, basestring_type):\n            logger = logging.getLogger(logger)\n        self.logger = logger\n        self.regex = re.compile(regex)\n        self.required = required\n        self.matched = False\n        self.logged_stack = False\n\n    def filter(self, record):\n        if record.exc_info:\n            self.logged_stack = True\n        message = record.getMessage()\n        if self.regex.match(message):\n            self.matched = True\n            return False\n        return True\n\n    def __enter__(self):\n        self.logger.addFilter(self)\n        return self\n\n    def __exit__(self, typ, value, tb):\n        self.logger.removeFilter(self)\n        if not typ and self.required and not self.matched:\n            raise Exception(\"did not get expected log message\")\n\n\ndef main(**kwargs):\n    \"\"\"A simple test runner.\n\n    This test runner is essentially equivalent to `unittest.main` from\n    the standard library, but adds support for tornado-style option\n    parsing and log formatting. It is *not* necessary to use this\n    `main` function to run tests using `AsyncTestCase`; these tests\n    are self-contained and can run with any test runner.\n\n    The easiest way to run a test is via the command line::\n\n        python -m tornado.testing tornado.test.stack_context_test\n\n    See the standard library unittest module for ways in which tests can\n    be specified.\n\n    Projects with many tests may wish to define a test script like\n    ``tornado/test/runtests.py``.  This script should define a method\n    ``all()`` which returns a test suite and then call\n    `tornado.testing.main()`.  Note that even when a test script is\n    used, the ``all()`` test suite may be overridden by naming a\n    single test on the command line::\n\n        # Runs all tests\n        python -m tornado.test.runtests\n        # Runs one test\n        python -m tornado.test.runtests tornado.test.stack_context_test\n\n    Additional keyword arguments passed through to ``unittest.main()``.\n    For example, use ``tornado.testing.main(verbosity=2)``\n    to show many test details as they are run.\n    See http://docs.python.org/library/unittest.html#unittest.main\n    for full argument list.\n    \"\"\"\n    from tornado.options import define, options, parse_command_line\n\n    define('exception_on_interrupt', type=bool, default=True,\n           help=(\"If true (default), ctrl-c raises a KeyboardInterrupt \"\n                 \"exception.  This prints a stack trace but cannot interrupt \"\n                 \"certain operations.  If false, the process is more reliably \"\n                 \"killed, but does not print a stack trace.\"))\n\n    # support the same options as unittest's command-line interface\n    define('verbose', type=bool)\n    define('quiet', type=bool)\n    define('failfast', type=bool)\n    define('catch', type=bool)\n    define('buffer', type=bool)\n\n    argv = [sys.argv[0]] + parse_command_line(sys.argv)\n\n    if not options.exception_on_interrupt:\n        signal.signal(signal.SIGINT, signal.SIG_DFL)\n\n    if options.verbose is not None:\n        kwargs['verbosity'] = 2\n    if options.quiet is not None:\n        kwargs['verbosity'] = 0\n    if options.failfast is not None:\n        kwargs['failfast'] = True\n    if options.catch is not None:\n        kwargs['catchbreak'] = True\n    if options.buffer is not None:\n        kwargs['buffer'] = True\n\n    if __name__ == '__main__' and len(argv) == 1:\n        print(\"No tests specified\", file=sys.stderr)\n        sys.exit(1)\n    try:\n        # In order to be able to run tests by their fully-qualified name\n        # on the command line without importing all tests here,\n        # module must be set to None.  Python 3.2's unittest.main ignores\n        # defaultTest if no module is given (it tries to do its own\n        # test discovery, which is incompatible with auto2to3), so don't\n        # set module if we're not asking for a specific test.\n        if len(argv) > 1:\n            unittest.main(module=None, argv=argv, **kwargs)\n        else:\n            unittest.main(defaultTest=\"all\", argv=argv, **kwargs)\n    except SystemExit as e:\n        if e.code == 0:\n            gen_log.info('PASS')\n        else:\n            gen_log.error('FAIL')\n        raise\n\n\nif __name__ == '__main__':\n    main()\n",
            "new_file_content": "#!/usr/bin/env python\n\"\"\"Support classes for automated testing.\n\n* `AsyncTestCase` and `AsyncHTTPTestCase`:  Subclasses of unittest.TestCase\n  with additional support for testing asynchronous (`.IOLoop`-based) code.\n\n* `ExpectLog`: Make test logs less spammy.\n\n* `main()`: A simple test runner (wrapper around unittest.main()) with support\n  for the tornado.autoreload module to rerun the tests when code changes.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\ntry:\n    from tornado import gen\n    from tornado.httpclient import AsyncHTTPClient\n    from tornado.httpserver import HTTPServer\n    from tornado.simple_httpclient import SimpleAsyncHTTPClient\n    from tornado.ioloop import IOLoop, TimeoutError\n    from tornado import netutil\n    from tornado.process import Subprocess\nexcept ImportError:\n    # These modules are not importable on app engine.  Parts of this module\n    # won't work, but e.g. main() will.\n    AsyncHTTPClient = None  # type: ignore\n    gen = None  # type: ignore\n    HTTPServer = None  # type: ignore\n    IOLoop = None  # type: ignore\n    netutil = None  # type: ignore\n    SimpleAsyncHTTPClient = None  # type: ignore\n    Subprocess = None  # type: ignore\nfrom tornado.log import gen_log, app_log\nfrom tornado.stack_context import ExceptionStackContext\nfrom tornado.util import raise_exc_info, basestring_type, PY3\nimport functools\nimport inspect\nimport logging\nimport os\nimport re\nimport signal\nimport socket\nimport sys\n\nif PY3:\n    from io import StringIO\nelse:\n    from cStringIO import StringIO\n\ntry:\n    from collections.abc import Generator as GeneratorType  # type: ignore\nexcept ImportError:\n    from types import GeneratorType  # type: ignore\n\nif sys.version_info >= (3, 5):\n    iscoroutine = inspect.iscoroutine  # type: ignore\n    iscoroutinefunction = inspect.iscoroutinefunction  # type: ignore\nelse:\n    iscoroutine = iscoroutinefunction = lambda f: False\n\n# Tornado's own test suite requires the updated unittest module\n# (either py27+ or unittest2) so tornado.test.util enforces\n# this requirement, but for other users of tornado.testing we want\n# to allow the older version if unitest2 is not available.\nif PY3:\n    # On python 3, mixing unittest2 and unittest (including doctest)\n    # doesn't seem to work, so always use unittest.\n    import unittest\nelse:\n    # On python 2, prefer unittest2 when available.\n    try:\n        import unittest2 as unittest  # type: ignore\n    except ImportError:\n        import unittest  # type: ignore\n\n\ndef bind_unused_port(reuse_port=False):\n    \"\"\"Binds a server socket to an available port on localhost.\n\n    Returns a tuple (socket, port).\n\n    .. versionchanged:: 4.4\n       Always binds to ``127.0.0.1`` without resolving the name\n       ``localhost``.\n    \"\"\"\n    sock = netutil.bind_sockets(None, '127.0.0.1', family=socket.AF_INET,\n                                reuse_port=reuse_port)[0]\n    port = sock.getsockname()[1]\n    return sock, port\n\n\ndef get_async_test_timeout():\n    \"\"\"Get the global timeout setting for async tests.\n\n    Returns a float, the timeout in seconds.\n\n    .. versionadded:: 3.1\n    \"\"\"\n    try:\n        return float(os.environ.get('ASYNC_TEST_TIMEOUT'))\n    except (ValueError, TypeError):\n        return 5\n\n\nclass _TestMethodWrapper(object):\n    \"\"\"Wraps a test method to raise an error if it returns a value.\n\n    This is mainly used to detect undecorated generators (if a test\n    method yields it must use a decorator to consume the generator),\n    but will also detect other kinds of return values (these are not\n    necessarily errors, but we alert anyway since there is no good\n    reason to return a value from a test).\n    \"\"\"\n    def __init__(self, orig_method):\n        self.orig_method = orig_method\n\n    def __call__(self, *args, **kwargs):\n        result = self.orig_method(*args, **kwargs)\n        if isinstance(result, GeneratorType) or iscoroutine(result):\n            raise TypeError(\"Generator and coroutine test methods should be\"\n                            \" decorated with tornado.testing.gen_test\")\n        elif result is not None:\n            raise ValueError(\"Return value from test method ignored: %r\" %\n                             result)\n\n    def __getattr__(self, name):\n        \"\"\"Proxy all unknown attributes to the original method.\n\n        This is important for some of the decorators in the `unittest`\n        module, such as `unittest.skipIf`.\n        \"\"\"\n        return getattr(self.orig_method, name)\n\n\nclass AsyncTestCase(unittest.TestCase):\n    \"\"\"`~unittest.TestCase` subclass for testing `.IOLoop`-based\n    asynchronous code.\n\n    The unittest framework is synchronous, so the test must be\n    complete by the time the test method returns.  This means that\n    asynchronous code cannot be used in quite the same way as usual.\n    To write test functions that use the same ``yield``-based patterns\n    used with the `tornado.gen` module, decorate your test methods\n    with `tornado.testing.gen_test` instead of\n    `tornado.gen.coroutine`.  This class also provides the `stop()`\n    and `wait()` methods for a more manual style of testing.  The test\n    method itself must call ``self.wait()``, and asynchronous\n    callbacks should call ``self.stop()`` to signal completion.\n\n    By default, a new `.IOLoop` is constructed for each test and is available\n    as ``self.io_loop``.  If the code being tested requires a\n    global `.IOLoop`, subclasses should override `get_new_ioloop` to return it.\n\n    The `.IOLoop`'s ``start`` and ``stop`` methods should not be\n    called directly.  Instead, use `self.stop <stop>` and `self.wait\n    <wait>`.  Arguments passed to ``self.stop`` are returned from\n    ``self.wait``.  It is possible to have multiple ``wait``/``stop``\n    cycles in the same test.\n\n    Example::\n\n        # This test uses coroutine style.\n        class MyTestCase(AsyncTestCase):\n            @tornado.testing.gen_test\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                response = yield client.fetch(\"http://www.tornadoweb.org\")\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses argument passing between self.stop and self.wait.\n        class MyTestCase2(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.stop)\n                response = self.wait()\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses an explicit callback-based style.\n        class MyTestCase3(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.handle_fetch)\n                self.wait()\n\n            def handle_fetch(self, response):\n                # Test contents of response (failures and exceptions here\n                # will cause self.wait() to throw an exception and end the\n                # test).\n                # Exceptions thrown here are magically propagated to\n                # self.wait() in test_http_fetch() via stack_context.\n                self.assertIn(\"FriendFeed\", response.body)\n                self.stop()\n    \"\"\"\n    def __init__(self, methodName='runTest'):\n        super(AsyncTestCase, self).__init__(methodName)\n        self.__stopped = False\n        self.__running = False\n        self.__failure = None\n        self.__stop_args = None\n        self.__timeout = None\n\n        # It's easy to forget the @gen_test decorator, but if you do\n        # the test will silently be ignored because nothing will consume\n        # the generator.  Replace the test method with a wrapper that will\n        # make sure it's not an undecorated generator.\n        setattr(self, methodName, _TestMethodWrapper(getattr(self, methodName)))\n\n    def setUp(self):\n        super(AsyncTestCase, self).setUp()\n        self.io_loop = self.get_new_ioloop()\n        self.io_loop.make_current()\n\n    def tearDown(self):\n        # Clean up Subprocess, so it can be used again with a new ioloop.\n        Subprocess.uninitialize()\n        self.io_loop.clear_current()\n        # Try to clean up any file descriptors left open in the ioloop.\n        # This avoids leaks, especially when tests are run repeatedly\n        # in the same process with autoreload (because curl does not\n        # set FD_CLOEXEC on its file descriptors)\n        self.io_loop.close(all_fds=True)\n        super(AsyncTestCase, self).tearDown()\n        # In case an exception escaped or the StackContext caught an exception\n        # when there wasn't a wait() to re-raise it, do so here.\n        # This is our last chance to raise an exception in a way that the\n        # unittest machinery understands.\n        self.__rethrow()\n\n    def get_new_ioloop(self):\n        \"\"\"Creates a new `.IOLoop` for this test.  May be overridden in\n        subclasses for tests that require a specific `.IOLoop` (usually\n        the singleton `.IOLoop.instance()`).\n        \"\"\"\n        return IOLoop()\n\n    def _handle_exception(self, typ, value, tb):\n        if self.__failure is None:\n            self.__failure = (typ, value, tb)\n        else:\n            app_log.error(\"multiple unhandled exceptions in test\",\n                          exc_info=(typ, value, tb))\n        self.stop()\n        return True\n\n    def __rethrow(self):\n        if self.__failure is not None:\n            failure = self.__failure\n            self.__failure = None\n            raise_exc_info(failure)\n\n    def run(self, result=None):\n        with ExceptionStackContext(self._handle_exception):\n            super(AsyncTestCase, self).run(result)\n        # As a last resort, if an exception escaped super.run() and wasn't\n        # re-raised in tearDown, raise it here.  This will cause the\n        # unittest run to fail messily, but that's better than silently\n        # ignoring an error.\n        self.__rethrow()\n\n    def stop(self, _arg=None, **kwargs):\n        \"\"\"Stops the `.IOLoop`, causing one pending (or future) call to `wait()`\n        to return.\n\n        Keyword arguments or a single positional argument passed to `stop()` are\n        saved and will be returned by `wait()`.\n        \"\"\"\n        assert _arg is None or not kwargs\n        self.__stop_args = kwargs or _arg\n        if self.__running:\n            self.io_loop.stop()\n            self.__running = False\n        self.__stopped = True\n\n    def wait(self, condition=None, timeout=None):\n        \"\"\"Runs the `.IOLoop` until stop is called or timeout has passed.\n\n        In the event of a timeout, an exception will be thrown. The\n        default timeout is 5 seconds; it may be overridden with a\n        ``timeout`` keyword argument or globally with the\n        ``ASYNC_TEST_TIMEOUT`` environment variable.\n\n        If ``condition`` is not None, the `.IOLoop` will be restarted\n        after `stop()` until ``condition()`` returns true.\n\n        .. versionchanged:: 3.1\n           Added the ``ASYNC_TEST_TIMEOUT`` environment variable.\n        \"\"\"\n        if timeout is None:\n            timeout = get_async_test_timeout()\n\n        if not self.__stopped:\n            if timeout:\n                def timeout_func():\n                    try:\n                        raise self.failureException(\n                            'Async operation timed out after %s seconds' %\n                            timeout)\n                    except Exception:\n                        self.__failure = sys.exc_info()\n                    self.stop()\n                self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func)\n            while True:\n                self.__running = True\n                self.io_loop.start()\n                if (self.__failure is not None or\n                        condition is None or condition()):\n                    break\n            if self.__timeout is not None:\n                self.io_loop.remove_timeout(self.__timeout)\n                self.__timeout = None\n        assert self.__stopped\n        self.__stopped = False\n        self.__rethrow()\n        result = self.__stop_args\n        self.__stop_args = None\n        return result\n\n\nclass AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://127.0.0.1:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()\n\n\nclass AsyncHTTPSTestCase(AsyncHTTPTestCase):\n    \"\"\"A test case that starts an HTTPS server.\n\n    Interface is generally the same as `AsyncHTTPTestCase`.\n    \"\"\"\n    def get_http_client(self):\n        return AsyncHTTPClient(force_instance=True,\n                               defaults=dict(validate_cert=False))\n\n    def get_httpserver_options(self):\n        return dict(ssl_options=self.get_ssl_options())\n\n    def get_ssl_options(self):\n        \"\"\"May be overridden by subclasses to select SSL options.\n\n        By default includes a self-signed testing certificate.\n        \"\"\"\n        # Testing keys were generated with:\n        # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509\n        module_dir = os.path.dirname(__file__)\n        return dict(\n            certfile=os.path.join(module_dir, 'test', 'test.crt'),\n            keyfile=os.path.join(module_dir, 'test', 'test.key'))\n\n    def get_protocol(self):\n        return 'https'\n\n\ndef gen_test(func=None, timeout=None):\n    \"\"\"Testing equivalent of ``@gen.coroutine``, to be applied to test methods.\n\n    ``@gen.coroutine`` cannot be used on tests because the `.IOLoop` is not\n    already running.  ``@gen_test`` should be applied to test methods\n    on subclasses of `AsyncTestCase`.\n\n    Example::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test\n            def test_something(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    By default, ``@gen_test`` times out after 5 seconds. The timeout may be\n    overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable,\n    or for each test with the ``timeout`` keyword argument::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test(timeout=10)\n            def test_something_slow(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`,\n    `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield\n    self.http_client.fetch(self.get_url())`` as shown above instead.\n\n    .. versionadded:: 3.1\n       The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment\n       variable.\n\n    .. versionchanged:: 4.0\n       The wrapper now passes along ``*args, **kwargs`` so it can be used\n       on functions with arguments.\n\n    \"\"\"\n    if timeout is None:\n        timeout = get_async_test_timeout()\n\n    def wrap(f):\n        # Stack up several decorators to allow us to access the generator\n        # object itself.  In the innermost wrapper, we capture the generator\n        # and save it in an attribute of self.  Next, we run the wrapped\n        # function through @gen.coroutine.  Finally, the coroutine is\n        # wrapped again to make it synchronous with run_sync.\n        #\n        # This is a good case study arguing for either some sort of\n        # extensibility in the gen decorators or cancellation support.\n        @functools.wraps(f)\n        def pre_coroutine(self, *args, **kwargs):\n            result = f(self, *args, **kwargs)\n            if isinstance(result, GeneratorType) or iscoroutine(result):\n                self._test_generator = result\n            else:\n                self._test_generator = None\n            return result\n\n        if iscoroutinefunction(f):\n            coro = pre_coroutine\n        else:\n            coro = gen.coroutine(pre_coroutine)\n\n        @functools.wraps(coro)\n        def post_coroutine(self, *args, **kwargs):\n            try:\n                return self.io_loop.run_sync(\n                    functools.partial(coro, self, *args, **kwargs),\n                    timeout=timeout)\n            except TimeoutError as e:\n                # run_sync raises an error with an unhelpful traceback.\n                # Throw it back into the generator or coroutine so the stack\n                # trace is replaced by the point where the test is stopped.\n                self._test_generator.throw(e)\n                # In case the test contains an overly broad except clause,\n                # we may get back here.  In this case re-raise the original\n                # exception, which is better than nothing.\n                raise\n        return post_coroutine\n\n    if func is not None:\n        # Used like:\n        #     @gen_test\n        #     def f(self):\n        #         pass\n        return wrap(func)\n    else:\n        # Used like @gen_test(timeout=10)\n        return wrap\n\n\n# Without this attribute, nosetests will try to run gen_test as a test\n# anywhere it is imported.\ngen_test.__test__ = False  # type: ignore\n\n\nclass ExpectLog(logging.Filter):\n    \"\"\"Context manager to capture and suppress expected log output.\n\n    Useful to make tests of error conditions less noisy, while still\n    leaving unexpected log entries visible.  *Not thread safe.*\n\n    The attribute ``logged_stack`` is set to true if any exception\n    stack trace was logged.\n\n    Usage::\n\n        with ExpectLog('tornado.application', \"Uncaught exception\"):\n            error_response = self.fetch(\"/some_page\")\n\n    .. versionchanged:: 4.3\n       Added the ``logged_stack`` attribute.\n    \"\"\"\n    def __init__(self, logger, regex, required=True):\n        \"\"\"Constructs an ExpectLog context manager.\n\n        :param logger: Logger object (or name of logger) to watch.  Pass\n            an empty string to watch the root logger.\n        :param regex: Regular expression to match.  Any log entries on\n            the specified logger that match this regex will be suppressed.\n        :param required: If true, an exception will be raised if the end of\n            the ``with`` statement is reached without matching any log entries.\n        \"\"\"\n        if isinstance(logger, basestring_type):\n            logger = logging.getLogger(logger)\n        self.logger = logger\n        self.regex = re.compile(regex)\n        self.required = required\n        self.matched = False\n        self.logged_stack = False\n\n    def filter(self, record):\n        if record.exc_info:\n            self.logged_stack = True\n        message = record.getMessage()\n        if self.regex.match(message):\n            self.matched = True\n            return False\n        return True\n\n    def __enter__(self):\n        self.logger.addFilter(self)\n        return self\n\n    def __exit__(self, typ, value, tb):\n        self.logger.removeFilter(self)\n        if not typ and self.required and not self.matched:\n            raise Exception(\"did not get expected log message\")\n\n\ndef main(**kwargs):\n    \"\"\"A simple test runner.\n\n    This test runner is essentially equivalent to `unittest.main` from\n    the standard library, but adds support for tornado-style option\n    parsing and log formatting. It is *not* necessary to use this\n    `main` function to run tests using `AsyncTestCase`; these tests\n    are self-contained and can run with any test runner.\n\n    The easiest way to run a test is via the command line::\n\n        python -m tornado.testing tornado.test.stack_context_test\n\n    See the standard library unittest module for ways in which tests can\n    be specified.\n\n    Projects with many tests may wish to define a test script like\n    ``tornado/test/runtests.py``.  This script should define a method\n    ``all()`` which returns a test suite and then call\n    `tornado.testing.main()`.  Note that even when a test script is\n    used, the ``all()`` test suite may be overridden by naming a\n    single test on the command line::\n\n        # Runs all tests\n        python -m tornado.test.runtests\n        # Runs one test\n        python -m tornado.test.runtests tornado.test.stack_context_test\n\n    Additional keyword arguments passed through to ``unittest.main()``.\n    For example, use ``tornado.testing.main(verbosity=2)``\n    to show many test details as they are run.\n    See http://docs.python.org/library/unittest.html#unittest.main\n    for full argument list.\n    \"\"\"\n    from tornado.options import define, options, parse_command_line\n\n    define('exception_on_interrupt', type=bool, default=True,\n           help=(\"If true (default), ctrl-c raises a KeyboardInterrupt \"\n                 \"exception.  This prints a stack trace but cannot interrupt \"\n                 \"certain operations.  If false, the process is more reliably \"\n                 \"killed, but does not print a stack trace.\"))\n\n    # support the same options as unittest's command-line interface\n    define('verbose', type=bool)\n    define('quiet', type=bool)\n    define('failfast', type=bool)\n    define('catch', type=bool)\n    define('buffer', type=bool)\n\n    argv = [sys.argv[0]] + parse_command_line(sys.argv)\n\n    if not options.exception_on_interrupt:\n        signal.signal(signal.SIGINT, signal.SIG_DFL)\n\n    if options.verbose is not None:\n        kwargs['verbosity'] = 2\n    if options.quiet is not None:\n        kwargs['verbosity'] = 0\n    if options.failfast is not None:\n        kwargs['failfast'] = True\n    if options.catch is not None:\n        kwargs['catchbreak'] = True\n    if options.buffer is not None:\n        kwargs['buffer'] = True\n\n    if __name__ == '__main__' and len(argv) == 1:\n        print(\"No tests specified\", file=sys.stderr)\n        sys.exit(1)\n    try:\n        # In order to be able to run tests by their fully-qualified name\n        # on the command line without importing all tests here,\n        # module must be set to None.  Python 3.2's unittest.main ignores\n        # defaultTest if no module is given (it tries to do its own\n        # test discovery, which is incompatible with auto2to3), so don't\n        # set module if we're not asking for a specific test.\n        if len(argv) > 1:\n            unittest.main(module=None, argv=argv, **kwargs)\n        else:\n            unittest.main(defaultTest=\"all\", argv=argv, **kwargs)\n    except SystemExit as e:\n        if e.code == 0:\n            gen_log.info('PASS')\n        else:\n            gen_log.error('FAIL')\n        raise\n\n\nif __name__ == '__main__':\n    main()\n",
            "header": {
                "file": {
                    "path": "tornado/testing.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "b79ba592",
                "new_commit_hash": "86d4b574",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/testing.py"
            },
            "plus_file": {
                "path": "b/tornado/testing.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 407,
                            "length": 7
                        },
                        "new_range": {
                            "start": 407,
                            "length": 7
                        },
                        "section": "class AsyncHTTPTestCase(AsyncTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def get_url(self, path):",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "        return '%s://localhost:%s%s' % (self.get_protocol(),",
                                "type": "deleted"
                            },
                            {
                                "content": "        return '%s://127.0.0.1:%s%s' % (self.get_protocol(),",
                                "type": "added"
                            },
                            {
                                "content": "                                        self.get_http_port(), path)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def tearDown(self):",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/testing.py",
                            "type": "method",
                            "name": "AsyncHTTPTestCase.get_url",
                            "content": "class AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://localhost:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 408,
                            "end_lineno": 411,
                            "parent": {
                                "file_name": "tornado/testing.py",
                                "type": "class",
                                "name": "AsyncHTTPTestCase",
                                "content": "class AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://localhost:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 321,
                                "end_lineno": 418,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/testing.py",
                            "type": "class",
                            "name": "AsyncHTTPTestCase",
                            "content": "class AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://localhost:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 321,
                            "end_lineno": 418,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "a42b028ca26150b41ca537f08b06aff3163a682e^",
    "new_commit_hash": "a42b028ca26150b41ca537f08b06aff3163a682e",
    "commit_message": "Merge pull request #2187 from bdarnell/ipv6-detection\n\ntest: More robust avoidance of broken ipv6",
    "commit_date": "2017-11-05T11:08:04-05:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "a42b028ca26150b41ca537f08b06aff3163a682e",
    "test_file_codes": [
        "from __future__ import absolute_import, division, print_function\nfrom tornado.concurrent import Future\nfrom tornado import gen\nfrom tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str, to_basestring\nfrom tornado.httputil import format_timestamp\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import IOStream\nfrom tornado import locale\nfrom tornado.log import app_log, gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.template import DictLoader\nfrom tornado.testing import AsyncHTTPTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipBefore35, exec_test\nfrom tornado.util import ObjectDict, unicode_type, timedelta_to_seconds, PY3\nfrom tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish, removeslash, addslash, RedirectHandler as WebRedirectHandler, get_signature_key_version, GZipContentEncoding\n\nimport binascii\nimport contextlib\nimport copy\nimport datetime\nimport email.utils\nimport gzip\nfrom io import BytesIO\nimport itertools\nimport logging\nimport os\nimport re\nimport socket\n\nif PY3:\n    import urllib.parse as urllib_parse  # py3\nelse:\n    import urllib as urllib_parse  # py2\n\nwsgi_safe_tests = []\n\n\ndef relpath(*a):\n    return os.path.join(os.path.dirname(__file__), *a)\n\n\ndef wsgi_safe(cls):\n    wsgi_safe_tests.append(cls)\n    return cls\n\n\nclass WebTestCase(AsyncHTTPTestCase):\n    \"\"\"Base class for web tests that also supports WSGI mode.\n\n    Override get_handlers and get_app_kwargs instead of get_app.\n    Append to wsgi_safe to have it run in wsgi_test as well.\n    \"\"\"\n    def get_app(self):\n        self.app = Application(self.get_handlers(), **self.get_app_kwargs())\n        return self.app\n\n    def get_handlers(self):\n        raise NotImplementedError()\n\n    def get_app_kwargs(self):\n        return {}\n\n\nclass SimpleHandlerTestCase(WebTestCase):\n    \"\"\"Simplified base class for tests that work with a single handler class.\n\n    To use, define a nested class named ``Handler``.\n    \"\"\"\n    def get_handlers(self):\n        return [('/', self.Handler)]\n\n\nclass HelloHandler(RequestHandler):\n    def get(self):\n        self.write('hello')\n\n\nclass CookieTestRequestHandler(RequestHandler):\n    # stub out enough methods to make the secure_cookie functions work\n    def __init__(self, cookie_secret='0123456789', key_version=None):\n        # don't call super.__init__\n        self._cookies = {}\n        if key_version is None:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret))\n        else:\n            self.application = ObjectDict(settings=dict(cookie_secret=cookie_secret,\n                                                        key_version=key_version))\n\n    def get_cookie(self, name):\n        return self._cookies.get(name)\n\n    def set_cookie(self, name, value, expires_days=None):\n        self._cookies[name] = value\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV1Test(unittest.TestCase):\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1),\n                         b'bar')\n\n    def test_cookie_tampering_future_timestamp(self):\n        handler = CookieTestRequestHandler()\n        # this string base64-encodes to '12345678'\n        handler.set_secure_cookie('foo', binascii.a2b_hex(b'd76df8e7aefc'),\n                                  version=1)\n        cookie = handler._cookies['foo']\n        match = re.match(br'12345678\\|([0-9]+)\\|([0-9a-f]+)', cookie)\n        self.assertTrue(match)\n        timestamp = match.group(1)\n        sig = match.group(2)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '12345678', timestamp),\n            sig)\n        # shifting digits from payload to timestamp doesn't alter signature\n        # (this is not desirable behavior, just confirming that that's how it\n        # works)\n        self.assertEqual(\n            _create_signature_v1(handler.application.settings[\"cookie_secret\"],\n                                 'foo', '1234', b'5678' + timestamp),\n            sig)\n        # tamper with the cookie\n        handler._cookies['foo'] = utf8('1234|5678%s|%s' % (\n            to_basestring(timestamp), to_basestring(sig)))\n        # it gets rejected\n        with ExpectLog(gen_log, \"Cookie timestamp in future\"):\n            self.assertTrue(\n                handler.get_secure_cookie('foo', min_version=1) is None)\n\n    def test_arbitrary_bytes(self):\n        # Secure cookies accept arbitrary data (which is base64 encoded).\n        # Note that normal cookies accept only a subset of ascii.\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'\\xe9', version=1)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=1), b'\\xe9')\n\n\n# See SignedValueTest below for more.\nclass SecureCookieV2Test(unittest.TestCase):\n    KEY_VERSIONS = {\n        0: 'ajklasdf0ojaisdf',\n        1: 'aslkjasaolwkjsdf'\n    }\n\n    def test_round_trip(self):\n        handler = CookieTestRequestHandler()\n        handler.set_secure_cookie('foo', b'bar', version=2)\n        self.assertEqual(handler.get_secure_cookie('foo', min_version=2), b'bar')\n\n    def test_key_version_roundtrip(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_roundtrip_differing_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=1)\n        handler.set_secure_cookie('foo', b'bar')\n        self.assertEqual(handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_increment_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), b'bar')\n\n    def test_key_version_invalidate_version(self):\n        handler = CookieTestRequestHandler(cookie_secret=self.KEY_VERSIONS,\n                                           key_version=0)\n        handler.set_secure_cookie('foo', b'bar')\n        new_key_versions = self.KEY_VERSIONS.copy()\n        new_key_versions.pop(0)\n        new_handler = CookieTestRequestHandler(cookie_secret=new_key_versions,\n                                               key_version=1)\n        new_handler._cookies = handler._cookies\n        self.assertEqual(new_handler.get_secure_cookie('foo'), None)\n\n\nclass CookieTest(WebTestCase):\n    def get_handlers(self):\n        class SetCookieHandler(RequestHandler):\n            def get(self):\n                # Try setting cookies with different argument types\n                # to ensure that everything gets encoded correctly\n                self.set_cookie(\"str\", \"asdf\")\n                self.set_cookie(\"unicode\", u\"qwer\")\n                self.set_cookie(\"bytes\", b\"zxcv\")\n\n        class GetCookieHandler(RequestHandler):\n            def get(self):\n                self.write(self.get_cookie(\"foo\", \"default\"))\n\n        class SetCookieDomainHandler(RequestHandler):\n            def get(self):\n                # unicode domain and path arguments shouldn't break things\n                # either (see bug #285)\n                self.set_cookie(\"unicode_args\", \"blah\", domain=u\"foo.com\",\n                                path=u\"/foo\")\n\n        class SetCookieSpecialCharHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"equals\", \"a=b\")\n                self.set_cookie(\"semicolon\", \"a;b\")\n                self.set_cookie(\"quote\", 'a\"b')\n\n        class SetCookieOverwriteHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"b\", domain=\"example.com\")\n                self.set_cookie(\"c\", \"d\", domain=\"example.com\")\n                # A second call with the same name clobbers the first.\n                # Attributes from the first call are not carried over.\n                self.set_cookie(\"a\", \"e\")\n\n        class SetCookieMaxAgeHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", max_age=10)\n\n        class SetCookieExpiresDaysHandler(RequestHandler):\n            def get(self):\n                self.set_cookie(\"foo\", \"bar\", expires_days=10)\n\n        class SetCookieFalsyFlags(RequestHandler):\n            def get(self):\n                self.set_cookie(\"a\", \"1\", secure=True)\n                self.set_cookie(\"b\", \"1\", secure=False)\n                self.set_cookie(\"c\", \"1\", httponly=True)\n                self.set_cookie(\"d\", \"1\", httponly=False)\n\n        return [(\"/set\", SetCookieHandler),\n                (\"/get\", GetCookieHandler),\n                (\"/set_domain\", SetCookieDomainHandler),\n                (\"/special_char\", SetCookieSpecialCharHandler),\n                (\"/set_overwrite\", SetCookieOverwriteHandler),\n                (\"/set_max_age\", SetCookieMaxAgeHandler),\n                (\"/set_expires_days\", SetCookieExpiresDaysHandler),\n                (\"/set_falsy_flags\", SetCookieFalsyFlags)\n                ]\n\n    def test_set_cookie(self):\n        response = self.fetch(\"/set\")\n        self.assertEqual(sorted(response.headers.get_list(\"Set-Cookie\")),\n                         [\"bytes=zxcv; Path=/\",\n                          \"str=asdf; Path=/\",\n                          \"unicode=qwer; Path=/\",\n                          ])\n\n    def test_get_cookie(self):\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"foo=bar\"})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": 'foo=\"bar\"'})\n        self.assertEqual(response.body, b\"bar\")\n\n        response = self.fetch(\"/get\", headers={\"Cookie\": \"/=exception;\"})\n        self.assertEqual(response.body, b\"default\")\n\n    def test_set_cookie_domain(self):\n        response = self.fetch(\"/set_domain\")\n        self.assertEqual(response.headers.get_list(\"Set-Cookie\"),\n                         [\"unicode_args=blah; Domain=foo.com; Path=/foo\"])\n\n    def test_cookie_special_char(self):\n        response = self.fetch(\"/special_char\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        self.assertEqual(len(headers), 3)\n        self.assertEqual(headers[0], 'equals=\"a=b\"; Path=/')\n        self.assertEqual(headers[1], 'quote=\"a\\\\\"b\"; Path=/')\n        # python 2.7 octal-escapes the semicolon; older versions leave it alone\n        self.assertTrue(headers[2] in ('semicolon=\"a;b\"; Path=/',\n                                       'semicolon=\"a\\\\073b\"; Path=/'),\n                        headers[2])\n\n        data = [('foo=a=b', 'a=b'),\n                ('foo=\"a=b\"', 'a=b'),\n                ('foo=\"a;b\"', '\"a'),  # even quoted, \";\" is a delimiter\n                ('foo=a\\\\073b', 'a\\\\073b'),  # escapes only decoded in quotes\n                ('foo=\"a\\\\073b\"', 'a;b'),\n                ('foo=\"a\\\\\"b\"', 'a\"b'),\n                ]\n        for header, expected in data:\n            logging.debug(\"trying %r\", header)\n            response = self.fetch(\"/get\", headers={\"Cookie\": header})\n            self.assertEqual(response.body, utf8(expected))\n\n    def test_set_cookie_overwrite(self):\n        response = self.fetch(\"/set_overwrite\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"a=e; Path=/\", \"c=d; Domain=example.com; Path=/\"])\n\n    def test_set_cookie_max_age(self):\n        response = self.fetch(\"/set_max_age\")\n        headers = response.headers.get_list(\"Set-Cookie\")\n        self.assertEqual(sorted(headers),\n                         [\"foo=bar; Max-Age=10; Path=/\"])\n\n    def test_set_cookie_expires_days(self):\n        response = self.fetch(\"/set_expires_days\")\n        header = response.headers.get(\"Set-Cookie\")\n        match = re.match(\"foo=bar; expires=(?P<expires>.+); Path=/\", header)\n        self.assertIsNotNone(match)\n\n        expires = datetime.datetime.utcnow() + datetime.timedelta(days=10)\n        header_expires = datetime.datetime(\n            *email.utils.parsedate(match.groupdict()[\"expires\"])[:6])\n        self.assertTrue(abs(timedelta_to_seconds(expires - header_expires)) < 10)\n\n    def test_set_cookie_false_flags(self):\n        response = self.fetch(\"/set_falsy_flags\")\n        headers = sorted(response.headers.get_list(\"Set-Cookie\"))\n        # The secure and httponly headers are capitalized in py35 and\n        # lowercase in older versions.\n        self.assertEqual(headers[0].lower(), 'a=1; path=/; secure')\n        self.assertEqual(headers[1].lower(), 'b=1; path=/')\n        self.assertEqual(headers[2].lower(), 'c=1; httponly; path=/')\n        self.assertEqual(headers[3].lower(), 'd=1; path=/')\n\n\nclass AuthRedirectRequestHandler(RequestHandler):\n    def initialize(self, login_url):\n        self.login_url = login_url\n\n    def get_login_url(self):\n        return self.login_url\n\n    @authenticated\n    def get(self):\n        # we'll never actually get here because the test doesn't follow redirects\n        self.send_error(500)\n\n\nclass AuthRedirectTest(WebTestCase):\n    def get_handlers(self):\n        return [('/relative', AuthRedirectRequestHandler,\n                 dict(login_url='/login')),\n                ('/absolute', AuthRedirectRequestHandler,\n                 dict(login_url='http://example.com/login'))]\n\n    def test_relative_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/relative'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/login?next=%2Frelative')\n\n    def test_absolute_auth_redirect(self):\n        self.http_client.fetch(self.get_url('/absolute'), self.stop,\n                               follow_redirects=False)\n        response = self.wait()\n        self.assertEqual(response.code, 302)\n        self.assertTrue(re.match(\n            'http://example.com/login\\?next=http%3A%2F%2F127.0.0.1%3A[0-9]+%2Fabsolute',\n            response.headers['Location']), response.headers['Location'])\n\n\nclass ConnectionCloseHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n\n    @asynchronous\n    def get(self):\n        self.test.on_handler_waiting()\n\n    def on_connection_close(self):\n        self.test.on_connection_close()\n\n\nclass ConnectionCloseTest(WebTestCase):\n    def get_handlers(self):\n        return [('/', ConnectionCloseHandler, dict(test=self))]\n\n    def test_connection_close(self):\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        self.stream = IOStream(s)\n        self.stream.write(b\"GET / HTTP/1.0\\r\\n\\r\\n\")\n        self.wait()\n\n    def on_handler_waiting(self):\n        logging.debug('handler waiting')\n        self.stream.close()\n\n    def on_connection_close(self):\n        logging.debug('connection closed')\n        self.stop()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self, *path_args):\n        # Type checks: web.py interfaces convert argument values to\n        # unicode strings (by default, but see also decode_argument).\n        # In httpserver.py (i.e. self.request.arguments), they're left\n        # as bytes.  Keys are always native strings.\n        for key in self.request.arguments:\n            if type(key) != str:\n                raise Exception(\"incorrect type for key: %r\" % type(key))\n            for value in self.request.arguments[key]:\n                if type(value) != bytes:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n            for value in self.get_arguments(key):\n                if type(value) != unicode_type:\n                    raise Exception(\"incorrect type for value: %r\" %\n                                    type(value))\n        for arg in path_args:\n            if type(arg) != unicode_type:\n                raise Exception(\"incorrect type for path arg: %r\" % type(arg))\n        self.write(dict(path=self.request.path,\n                        path_args=path_args,\n                        args=recursive_unicode(self.request.arguments)))\n\n\nclass RequestEncodingTest(WebTestCase):\n    def get_handlers(self):\n        return [(\"/group/(.*)\", EchoHandler),\n                (\"/slashes/([^/]*)/([^/]*)\", EchoHandler),\n                ]\n\n    def fetch_json(self, path):\n        return json_decode(self.fetch(path).body)\n\n    def test_group_question_mark(self):\n        # Ensure that url-encoded question marks are handled properly\n        self.assertEqual(self.fetch_json('/group/%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={}))\n        self.assertEqual(self.fetch_json('/group/%3F?%3F=%3F'),\n                         dict(path='/group/%3F', path_args=['?'], args={'?': ['?']}))\n\n    def test_group_encoding(self):\n        # Path components and query arguments should be decoded the same way\n        self.assertEqual(self.fetch_json('/group/%C3%A9?arg=%C3%A9'),\n                         {u\"path\": u\"/group/%C3%A9\",\n                          u\"path_args\": [u\"\\u00e9\"],\n                          u\"args\": {u\"arg\": [u\"\\u00e9\"]}})\n\n    def test_slashes(self):\n        # Slashes may be escaped to appear as a single \"directory\" in the path,\n        # but they are then unescaped when passed to the get() method.\n        self.assertEqual(self.fetch_json('/slashes/foo/bar'),\n                         dict(path=\"/slashes/foo/bar\",\n                              path_args=[\"foo\", \"bar\"],\n                              args={}))\n        self.assertEqual(self.fetch_json('/slashes/a%2Fb/c%2Fd'),\n                         dict(path=\"/slashes/a%2Fb/c%2Fd\",\n                              path_args=[\"a/b\", \"c/d\"],\n                              args={}))\n\n    def test_error(self):\n        # Percent signs (encoded as %25) should not mess up printf-style\n        # messages in logs\n        with ExpectLog(gen_log, \".*Invalid unicode\"):\n            self.fetch(\"/group/?arg=%25%e9\")\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n\n        self.check_type('status', self.get_status(), int)\n\n        # get_argument is an exception from the general rule of using\n        # type str for non-body data mainly for historical reasons.\n        self.check_type('argument', self.get_argument('foo'), unicode_type)\n        self.check_type('cookie_key', list(self.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.cookies.values())[0].value, str)\n\n        # Secure cookies return bytes because they can contain arbitrary\n        # data, but regular cookies are native strings.\n        if list(self.cookies.keys()) != ['asdf']:\n            raise Exception(\"unexpected values for cookie keys: %r\" %\n                            self.cookies.keys())\n        self.check_type('get_secure_cookie', self.get_secure_cookie('asdf'), bytes)\n        self.check_type('get_cookie', self.get_cookie('asdf'), str)\n\n        self.check_type('xsrf_token', self.xsrf_token, bytes)\n        self.check_type('xsrf_form_html', self.xsrf_form_html(), str)\n\n        self.check_type('reverse_url', self.reverse_url('typecheck', 'foo'), str)\n\n        self.check_type('request_summary', self._request_summary(), str)\n\n    def get(self, path_component):\n        # path_component uses type unicode instead of str for consistency\n        # with get_argument()\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def post(self, path_component):\n        self.check_type('path_component', path_component, unicode_type)\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass DecodeArgHandler(RequestHandler):\n    def decode_argument(self, value, name=None):\n        if type(value) != bytes:\n            raise Exception(\"unexpected type for value: %r\" % type(value))\n        # use self.request.arguments directly to avoid recursion\n        if 'encoding' in self.request.arguments:\n            return value.decode(to_unicode(self.request.arguments['encoding'][0]))\n        else:\n            return value\n\n    def get(self, arg):\n        def describe(s):\n            if type(s) == bytes:\n                return [\"bytes\", native_str(binascii.b2a_hex(s))]\n            elif type(s) == unicode_type:\n                return [\"unicode\", s]\n            raise Exception(\"unknown type\")\n        self.write({'path': describe(arg),\n                    'query': describe(self.get_argument(\"foo\")),\n                    })\n\n\nclass LinkifyHandler(RequestHandler):\n    def get(self):\n        self.render(\"linkify.html\", message=\"http://example.com\")\n\n\nclass UIModuleResourceHandler(RequestHandler):\n    def get(self):\n        self.render(\"page.html\", entries=[1, 2])\n\n\nclass OptionalPathHandler(RequestHandler):\n    def get(self, path):\n        self.write({\"path\": path})\n\n\nclass FlowControlHandler(RequestHandler):\n    # These writes are too small to demonstrate real flow control,\n    # but at least it shows that the callbacks get run.\n    @asynchronous\n    def get(self):\n        self.write(\"1\")\n        self.flush(callback=self.step2)\n\n    def step2(self):\n        self.write(\"2\")\n        self.flush(callback=self.step3)\n\n    def step3(self):\n        self.write(\"3\")\n        self.finish()\n\n\nclass MultiHeaderHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"x-overwrite\", \"1\")\n        self.set_header(\"X-Overwrite\", 2)\n        self.add_header(\"x-multi\", 3)\n        self.add_header(\"X-Multi\", \"4\")\n\n\nclass RedirectHandler(RequestHandler):\n    def get(self):\n        if self.get_argument('permanent', None) is not None:\n            self.redirect('/', permanent=int(self.get_argument('permanent')))\n        elif self.get_argument('status', None) is not None:\n            self.redirect('/', status=int(self.get_argument('status')))\n        else:\n            raise Exception(\"didn't get permanent or status arguments\")\n\n\nclass EmptyFlushCallbackHandler(RequestHandler):\n    @asynchronous\n    @gen.engine\n    def get(self):\n        # Ensure that the flush callback is run whether or not there\n        # was any output.  The gen.Task and direct yield forms are\n        # equivalent.\n        yield gen.Task(self.flush)  # \"empty\" flush, but writes headers\n        yield gen.Task(self.flush)  # empty flush\n        self.write(\"o\")\n        yield self.flush()  # flushes the \"o\"\n        yield self.flush()  # empty flush\n        self.finish(\"k\")\n\n\nclass HeaderInjectionHandler(RequestHandler):\n    def get(self):\n        try:\n            self.set_header(\"X-Foo\", \"foo\\r\\nX-Bar: baz\")\n            raise Exception(\"Didn't get expected exception\")\n        except ValueError as e:\n            if \"Unsafe header value\" in str(e):\n                self.finish(b\"ok\")\n            else:\n                raise\n\n\nclass GetArgumentHandler(RequestHandler):\n    def prepare(self):\n        if self.get_argument('source', None) == 'query':\n            method = self.get_query_argument\n        elif self.get_argument('source', None) == 'body':\n            method = self.get_body_argument\n        else:\n            method = self.get_argument\n        self.finish(method(\"foo\", \"default\"))\n\n\nclass GetArgumentsHandler(RequestHandler):\n    def prepare(self):\n        self.finish(dict(default=self.get_arguments(\"foo\"),\n                         query=self.get_query_arguments(\"foo\"),\n                         body=self.get_body_arguments(\"foo\")))\n\n\n# This test is shared with wsgi_test.py\n@wsgi_safe\nclass WSGISafeWebTest(WebTestCase):\n    COOKIE_SECRET = \"WebTest.COOKIE_SECRET\"\n\n    def get_app_kwargs(self):\n        loader = DictLoader({\n            \"linkify.html\": \"{% module linkify(message) %}\",\n            \"page.html\": \"\"\"\\\n<html><head></head><body>\n{% for e in entries %}\n{% module Template(\"entry.html\", entry=e) %}\n{% end %}\n</body></html>\"\"\",\n            \"entry.html\": \"\"\"\\\n{{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\", embedded_javascript=\"js_embed()\", css_files=[\"/base.css\", \"/foo.css\"], javascript_files=\"/common.js\", html_head=\"<meta>\", html_body='<script src=\"/analytics.js\"/>') }}\n<div class=\"entry\">...</div>\"\"\",\n        })\n        return dict(template_loader=loader,\n                    autoescape=\"xhtml_escape\",\n                    cookie_secret=self.COOKIE_SECRET)\n\n    def tearDown(self):\n        super(WSGISafeWebTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        urls = [\n            url(\"/typecheck/(.*)\", TypeCheckHandler, name='typecheck'),\n            url(\"/decode_arg/(.*)\", DecodeArgHandler, name='decode_arg'),\n            url(\"/decode_arg_kw/(?P<arg>.*)\", DecodeArgHandler),\n            url(\"/linkify\", LinkifyHandler),\n            url(\"/uimodule_resources\", UIModuleResourceHandler),\n            url(\"/optional_path/(.+)?\", OptionalPathHandler),\n            url(\"/multi_header\", MultiHeaderHandler),\n            url(\"/redirect\", RedirectHandler),\n            url(\"/web_redirect_permanent\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\"}),\n            url(\"/web_redirect\", WebRedirectHandler, {\"url\": \"/web_redirect_newpath\", \"permanent\": False}),\n            url(\"//web_redirect_double_slash\", WebRedirectHandler, {\"url\": '/web_redirect_newpath'}),\n            url(\"/header_injection\", HeaderInjectionHandler),\n            url(\"/get_argument\", GetArgumentHandler),\n            url(\"/get_arguments\", GetArgumentsHandler),\n        ]\n        return urls\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n    def test_types(self):\n        cookie_value = to_unicode(create_signed_value(self.COOKIE_SECRET,\n                                                      \"asdf\", \"qwer\"))\n        response = self.fetch(\"/typecheck/asdf?foo=bar\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value})\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck/asdf?foo=bar\", method=\"POST\",\n                              headers={\"Cookie\": \"asdf=\" + cookie_value},\n                              body=\"foo=bar\")\n\n    def test_decode_argument(self):\n        # These urls all decode to the same thing\n        urls = [\"/decode_arg/%C3%A9?foo=%C3%A9&encoding=utf-8\",\n                \"/decode_arg/%E9?foo=%E9&encoding=latin1\",\n                \"/decode_arg_kw/%E9?foo=%E9&encoding=latin1\",\n                ]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'\\u00e9'],\n                                    u'query': [u'unicode', u'\\u00e9'],\n                                    })\n\n        response = self.fetch(\"/decode_arg/%C3%A9?foo=%C3%A9\")\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {u'path': [u'bytes', u'c3a9'],\n                                u'query': [u'bytes', u'c3a9'],\n                                })\n\n    def test_decode_argument_invalid_unicode(self):\n        # test that invalid unicode in URLs causes 400, not 500\n        with ExpectLog(gen_log, \".*Invalid unicode.*\"):\n            response = self.fetch(\"/typecheck/invalid%FF\")\n            self.assertEqual(response.code, 400)\n            response = self.fetch(\"/typecheck/invalid?foo=%FF\")\n            self.assertEqual(response.code, 400)\n\n    def test_decode_argument_plus(self):\n        # These urls are all equivalent.\n        urls = [\"/decode_arg/1%20%2B%201?foo=1%20%2B%201&encoding=utf-8\",\n                \"/decode_arg/1%20+%201?foo=1+%2B+1&encoding=utf-8\"]\n        for req_url in urls:\n            response = self.fetch(req_url)\n            response.rethrow()\n            data = json_decode(response.body)\n            self.assertEqual(data, {u'path': [u'unicode', u'1 + 1'],\n                                    u'query': [u'unicode', u'1 + 1'],\n                                    })\n\n    def test_reverse_url(self):\n        self.assertEqual(self.app.reverse_url('decode_arg', 'foo'),\n                         '/decode_arg/foo')\n        self.assertEqual(self.app.reverse_url('decode_arg', 42),\n                         '/decode_arg/42')\n        self.assertEqual(self.app.reverse_url('decode_arg', b'\\xe9'),\n                         '/decode_arg/%E9')\n        self.assertEqual(self.app.reverse_url('decode_arg', u'\\u00e9'),\n                         '/decode_arg/%C3%A9')\n        self.assertEqual(self.app.reverse_url('decode_arg', '1 + 1'),\n                         '/decode_arg/1%20%2B%201')\n\n    def test_uimodule_unescaped(self):\n        response = self.fetch(\"/linkify\")\n        self.assertEqual(response.body,\n                         b\"<a href=\\\"http://example.com\\\">http://example.com</a>\")\n\n    def test_uimodule_resources(self):\n        response = self.fetch(\"/uimodule_resources\")\n        self.assertEqual(response.body, b\"\"\"\\\n<html><head><link href=\"/base.css\" type=\"text/css\" rel=\"stylesheet\"/><link href=\"/foo.css\" type=\"text/css\" rel=\"stylesheet\"/>\n<style type=\"text/css\">\n.entry { margin-bottom: 1em; }\n</style>\n<meta>\n</head><body>\n\n\n<div class=\"entry\">...</div>\n\n\n<div class=\"entry\">...</div>\n\n<script src=\"/common.js\" type=\"text/javascript\"></script>\n<script type=\"text/javascript\">\n//<![CDATA[\njs_embed()\n//]]>\n</script>\n<script src=\"/analytics.js\"/>\n</body></html>\"\"\")\n\n    def test_optional_path(self):\n        self.assertEqual(self.fetch_json(\"/optional_path/foo\"),\n                         {u\"path\": u\"foo\"})\n        self.assertEqual(self.fetch_json(\"/optional_path/\"),\n                         {u\"path\": None})\n\n    def test_multi_header(self):\n        response = self.fetch(\"/multi_header\")\n        self.assertEqual(response.headers[\"x-overwrite\"], \"2\")\n        self.assertEqual(response.headers.get_list(\"x-multi\"), [\"3\", \"4\"])\n\n    def test_redirect(self):\n        response = self.fetch(\"/redirect?permanent=1\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        response = self.fetch(\"/redirect?permanent=0\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        response = self.fetch(\"/redirect?status=307\", follow_redirects=False)\n        self.assertEqual(response.code, 307)\n\n    def test_web_redirect(self):\n        response = self.fetch(\"/web_redirect_permanent\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n        response = self.fetch(\"/web_redirect\", follow_redirects=False)\n        self.assertEqual(response.code, 302)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_web_redirect_double_slash(self):\n        response = self.fetch(\"//web_redirect_double_slash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/web_redirect_newpath')\n\n    def test_header_injection(self):\n        response = self.fetch(\"/header_injection\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_get_argument(self):\n        response = self.fetch(\"/get_argument?foo=bar\")\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?foo=\")\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument\")\n        self.assertEqual(response.body, b\"default\")\n\n        # Test merging of query and body arguments.\n        # In singular form, body arguments take precedence over query arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?foo=bar\", method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"hello\")\n        # In plural methods they are merged.\n        response = self.fetch(\"/get_arguments?foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(json_decode(response.body),\n                         dict(default=['bar', 'hello'],\n                              query=['bar'],\n                              body=['hello']))\n\n    def test_get_query_arguments(self):\n        # send as a post so we can ensure the separation between query\n        # string and body arguments.\n        body = urllib_parse.urlencode(dict(foo=\"hello\"))\n        response = self.fetch(\"/get_argument?source=query&foo=bar\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n        response = self.fetch(\"/get_argument?source=query&foo=\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n        response = self.fetch(\"/get_argument?source=query\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_get_body_arguments(self):\n        body = urllib_parse.urlencode(dict(foo=\"bar\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"bar\")\n\n        body = urllib_parse.urlencode(dict(foo=\"\"))\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"\")\n\n        body = urllib_parse.urlencode(dict())\n        response = self.fetch(\"/get_argument?source=body&foo=hello\",\n                              method=\"POST\", body=body)\n        self.assertEqual(response.body, b\"default\")\n\n    def test_no_gzip(self):\n        response = self.fetch('/get_argument')\n        self.assertNotIn('Accept-Encoding', response.headers.get('Vary', ''))\n        self.assertNotIn('gzip', response.headers.get('Content-Encoding', ''))\n\n\nclass NonWSGIWebTests(WebTestCase):\n    def get_handlers(self):\n        return [(\"/flow_control\", FlowControlHandler),\n                (\"/empty_flush\", EmptyFlushCallbackHandler),\n                ]\n\n    def test_flow_control(self):\n        self.assertEqual(self.fetch(\"/flow_control\").body, b\"123\")\n\n    def test_empty_flush(self):\n        response = self.fetch(\"/empty_flush\")\n        self.assertEqual(response.body, b\"ok\")\n\n\n@wsgi_safe\nclass ErrorResponseTest(WebTestCase):\n    def get_handlers(self):\n        class DefaultHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    raise HTTPError(int(self.get_argument(\"status\")))\n                1 / 0\n\n        class WriteErrorHandler(RequestHandler):\n            def get(self):\n                if self.get_argument(\"status\", None):\n                    self.send_error(int(self.get_argument(\"status\")))\n                else:\n                    1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                self.set_header(\"Content-Type\", \"text/plain\")\n                if \"exc_info\" in kwargs:\n                    self.write(\"Exception: %s\" % kwargs[\"exc_info\"][0].__name__)\n                else:\n                    self.write(\"Status: %d\" % status_code)\n\n        class FailedWriteErrorHandler(RequestHandler):\n            def get(self):\n                1 / 0\n\n            def write_error(self, status_code, **kwargs):\n                raise Exception(\"exception in write_error\")\n\n        return [url(\"/default\", DefaultHandler),\n                url(\"/write_error\", WriteErrorHandler),\n                url(\"/failed_write_error\", FailedWriteErrorHandler),\n                ]\n\n    def test_default(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/default\")\n            self.assertEqual(response.code, 500)\n            self.assertTrue(b\"500: Internal Server Error\" in response.body)\n\n            response = self.fetch(\"/default?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertTrue(b\"503: Service Unavailable\" in response.body)\n\n            response = self.fetch(\"/default?status=435\")\n            self.assertEqual(response.code, 435)\n            self.assertTrue(b\"435: Unknown\" in response.body)\n\n    def test_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"Exception: ZeroDivisionError\", response.body)\n\n            response = self.fetch(\"/write_error?status=503\")\n            self.assertEqual(response.code, 503)\n            self.assertEqual(b\"Status: 503\", response.body)\n\n    def test_failed_write_error(self):\n        with ExpectLog(app_log, \"Uncaught exception\"):\n            response = self.fetch(\"/failed_write_error\")\n            self.assertEqual(response.code, 500)\n            self.assertEqual(b\"\", response.body)\n\n\n@wsgi_safe\nclass StaticFileTest(WebTestCase):\n    # The expected MD5 hash of robots.txt, used in tests that call\n    # StaticFileHandler.get_version\n    robots_txt_hash = b\"f71d20196d4caf35b6a670db8c70b03d\"\n    static_dir = os.path.join(os.path.dirname(__file__), 'static')\n\n    def get_handlers(self):\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                with_v = int(self.get_argument('include_version', 1))\n                self.write(self.static_url(path, include_version=with_v))\n\n        class AbsoluteStaticUrlHandler(StaticUrlHandler):\n            include_host = True\n\n        class OverrideStaticUrlHandler(RequestHandler):\n            def get(self, path):\n                do_include = bool(self.get_argument(\"include_host\"))\n                self.include_host = not do_include\n\n                regular_url = self.static_url(path)\n                override_url = self.static_url(path, include_host=do_include)\n                if override_url == regular_url:\n                    return self.write(str(False))\n\n                protocol = self.request.protocol + \"://\"\n                protocol_length = len(protocol)\n                check_regular = regular_url.find(protocol, 0, protocol_length)\n                check_override = override_url.find(protocol, 0, protocol_length)\n\n                if do_include:\n                    result = (check_override == 0 and check_regular == -1)\n                else:\n                    result = (check_override == -1 and check_regular == 0)\n                self.write(str(result))\n\n        return [('/static_url/(.*)', StaticUrlHandler),\n                ('/abs_static_url/(.*)', AbsoluteStaticUrlHandler),\n                ('/override_static_url/(.*)', OverrideStaticUrlHandler),\n                ('/root_static/(.*)', StaticFileHandler, dict(path='/'))]\n\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'))\n\n    def test_static_files(self):\n        response = self.fetch('/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n\n        response = self.fetch('/static/robots.txt')\n        self.assertTrue(b\"Disallow: /\" in response.body)\n        self.assertEqual(response.headers.get(\"Content-Type\"), \"text/plain\")\n\n    def test_static_compressed_files(self):\n        response = self.fetch(\"/static/sample.xml.gz\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/gzip\")\n        response = self.fetch(\"/static/sample.xml.bz2\")\n        self.assertEqual(response.headers.get(\"Content-Type\"),\n                         \"application/octet-stream\")\n        # make sure the uncompressed file still has the correct type\n        response = self.fetch(\"/static/sample.xml\")\n        self.assertTrue(response.headers.get(\"Content-Type\")\n                        in set((\"text/xml\", \"application/xml\")))\n\n    def test_static_url(self):\n        response = self.fetch(\"/static_url/robots.txt\")\n        self.assertEqual(response.body,\n                         b\"/static/robots.txt?v=\" + self.robots_txt_hash)\n\n    def test_absolute_static_url(self):\n        response = self.fetch(\"/abs_static_url/robots.txt\")\n        self.assertEqual(response.body, (\n            utf8(self.get_url(\"/\")) +\n            b\"static/robots.txt?v=\" +\n            self.robots_txt_hash\n        ))\n\n    def test_relative_version_exclusion(self):\n        response = self.fetch(\"/static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body, b\"/static/robots.txt\")\n\n    def test_absolute_version_exclusion(self):\n        response = self.fetch(\"/abs_static_url/robots.txt?include_version=0\")\n        self.assertEqual(response.body,\n                         utf8(self.get_url(\"/\") + \"static/robots.txt\"))\n\n    def test_include_host_override(self):\n        self._trigger_include_host_check(False)\n        self._trigger_include_host_check(True)\n\n    def _trigger_include_host_check(self, include_host):\n        path = \"/override_static_url/robots.txt?include_host=%s\"\n        response = self.fetch(path % int(include_host))\n        self.assertEqual(response.body, utf8(str(True)))\n\n    def get_and_head(self, *args, **kwargs):\n        \"\"\"Performs a GET and HEAD request and returns the GET response.\n\n        Fails if any ``Content-*`` headers returned by the two requests\n        differ.\n        \"\"\"\n        head_response = self.fetch(*args, method=\"HEAD\", **kwargs)\n        get_response = self.fetch(*args, method=\"GET\", **kwargs)\n        content_headers = set()\n        for h in itertools.chain(head_response.headers, get_response.headers):\n            if h.startswith('Content-'):\n                content_headers.add(h)\n        for h in content_headers:\n            self.assertEqual(head_response.headers.get(h),\n                             get_response.headers.get(h),\n                             \"%s differs between GET (%s) and HEAD (%s)\" %\n                             (h, head_response.headers.get(h),\n                              get_response.headers.get(h)))\n        return get_response\n\n    def test_static_304_if_modified_since(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': response1.headers['Last-Modified']})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue('Content-Length' not in response2.headers)\n        self.assertTrue('Last-Modified' not in response2.headers)\n\n    def test_static_304_if_none_match(self):\n        response1 = self.get_and_head(\"/static/robots.txt\")\n        response2 = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-None-Match': response1.headers['Etag']})\n        self.assertEqual(response2.code, 304)\n\n    def test_static_if_modified_since_pre_epoch(self):\n        # On windows, the functions that work with time_t do not accept\n        # negative values, and at least one client (processing.js) seems\n        # to use if-modified-since 1/1/1960 as a cache-busting technique.\n        response = self.get_and_head(\"/static/robots.txt\", headers={\n            'If-Modified-Since': 'Fri, 01 Jan 1960 00:00:00 GMT'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_if_modified_since_time_zone(self):\n        # Instead of the value from Last-Modified, make requests with times\n        # chosen just before and after the known modification time\n        # of the file to ensure that the right time zone is being used\n        # when parsing If-Modified-Since.\n        stat = os.stat(relpath('static/robots.txt'))\n\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime - 1)})\n        self.assertEqual(response.code, 200)\n        response = self.get_and_head('/static/robots.txt', headers={\n            'If-Modified-Since': format_timestamp(stat.st_mtime + 1)})\n        self.assertEqual(response.code, 304)\n\n    def test_static_etag(self):\n        response = self.get_and_head('/static/robots.txt')\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_with_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-9'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b\"User-agent\")\n        self.assertEqual(utf8(response.headers.get(\"Etag\")),\n                         b'\"' + self.robots_txt_hash + b'\"')\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"10\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 0-9/26\")\n\n    def test_static_with_range_full_file(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-'})\n        # Note: Chrome refuses to play audio if it gets an HTTP 206 in response\n        # to ``Range: bytes=0-`` :(\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_full_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=0-10000000'})\n        self.assertEqual(response.code, 200)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"26\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), None)\n\n    def test_static_with_range_partial_past_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-10000000'})\n        self.assertEqual(response.code, 206)\n        robots_file_path = os.path.join(self.static_dir, \"robots.txt\")\n        with open(robots_file_path) as f:\n            self.assertEqual(response.body, utf8(f.read()[1:]))\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"25\")\n        self.assertEqual(response.headers.get(\"Content-Range\"), \"bytes 1-25/26\")\n\n    def test_static_with_range_end_edge(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=22-'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_with_range_neg_end(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-4'})\n        self.assertEqual(response.body, b\": /\\n\")\n        self.assertEqual(response.headers.get(\"Content-Length\"), \"4\")\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes 22-25/26\")\n\n    def test_static_invalid_range(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'asdf'})\n        self.assertEqual(response.code, 200)\n\n    def test_static_unsatisfiable_range_zero_suffix(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=-0'})\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n        self.assertEqual(response.code, 416)\n\n    def test_static_unsatisfiable_range_invalid_start(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=26'})\n        self.assertEqual(response.code, 416)\n        self.assertEqual(response.headers.get(\"Content-Range\"),\n                         \"bytes */26\")\n\n    def test_static_head(self):\n        response = self.fetch('/static/robots.txt', method='HEAD')\n        self.assertEqual(response.code, 200)\n        # No body was returned, but we did get the right content length.\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '26')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_head_range(self):\n        response = self.fetch('/static/robots.txt', method='HEAD',\n                              headers={'Range': 'bytes=1-4'})\n        self.assertEqual(response.code, 206)\n        self.assertEqual(response.body, b'')\n        self.assertEqual(response.headers['Content-Length'], '4')\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_range_if_none_match(self):\n        response = self.get_and_head('/static/robots.txt', headers={\n            'Range': 'bytes=1-4',\n            'If-None-Match': b'\"' + self.robots_txt_hash + b'\"'})\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.body, b'')\n        self.assertTrue('Content-Length' not in response.headers)\n        self.assertEqual(utf8(response.headers['Etag']),\n                         b'\"' + self.robots_txt_hash + b'\"')\n\n    def test_static_404(self):\n        response = self.get_and_head('/static/blarg')\n        self.assertEqual(response.code, 404)\n\n    def test_path_traversal_protection(self):\n        # curl_httpclient processes \"..\" on the client side, so we\n        # must test this with simple_httpclient.\n        self.http_client.close()\n        self.http_client = SimpleAsyncHTTPClient()\n        with ExpectLog(gen_log, \".*not in root static directory\"):\n            response = self.get_and_head('/static/../static_foo.txt')\n        # Attempted path traversal should result in 403, not 200\n        # (which means the check failed and the file was served)\n        # or 404 (which means that the file didn't exist and\n        # is probably a packaging error).\n        self.assertEqual(response.code, 403)\n\n    @unittest.skipIf(os.name != 'posix', 'non-posix OS')\n    def test_root_static_path(self):\n        # Sometimes people set the StaticFileHandler's path to '/'\n        # to disable Tornado's path validation (in conjunction with\n        # their own validation in get_absolute_path). Make sure\n        # that the stricter validation in 4.2.1 doesn't break them.\n        path = os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                            'static/robots.txt')\n        response = self.get_and_head('/root_static' + urllib_parse.quote(path))\n        self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass StaticDefaultFilenameTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return []\n\n    def test_static_default_filename(self):\n        response = self.fetch('/static/dir/', follow_redirects=False)\n        self.assertEqual(response.code, 200)\n        self.assertEqual(b'this is the index\\n', response.body)\n\n    def test_static_default_redirect(self):\n        response = self.fetch('/static/dir', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertTrue(response.headers['Location'].endswith('/static/dir/'))\n\n\n@wsgi_safe\nclass StaticFileWithPathTest(WebTestCase):\n    def get_app_kwargs(self):\n        return dict(static_path=relpath('static'),\n                    static_handler_args=dict(default_filename='index.html'))\n\n    def get_handlers(self):\n        return [(\"/foo/(.*)\", StaticFileHandler, {\n            \"path\": relpath(\"templates/\"),\n        })]\n\n    def test_serve(self):\n        response = self.fetch(\"/foo/utf8.html\")\n        self.assertEqual(response.body, b\"H\\xc3\\xa9llo\\n\")\n\n\n@wsgi_safe\nclass CustomStaticFileTest(WebTestCase):\n    def get_handlers(self):\n        class MyStaticFileHandler(StaticFileHandler):\n            @classmethod\n            def make_static_url(cls, settings, path):\n                version_hash = cls.get_version(settings, path)\n                extension_index = path.rindex('.')\n                before_version = path[:extension_index]\n                after_version = path[(extension_index + 1):]\n                return '/static/%s.%s.%s' % (before_version, version_hash,\n                                             after_version)\n\n            def parse_url_path(self, url_path):\n                extension_index = url_path.rindex('.')\n                version_index = url_path.rindex('.', 0, extension_index)\n                return '%s%s' % (url_path[:version_index],\n                                 url_path[extension_index:])\n\n            @classmethod\n            def get_absolute_path(cls, settings, path):\n                return 'CustomStaticFileTest:' + path\n\n            def validate_absolute_path(self, root, absolute_path):\n                return absolute_path\n\n            @classmethod\n            def get_content(self, path, start=None, end=None):\n                assert start is None and end is None\n                if path == 'CustomStaticFileTest:foo.txt':\n                    return b'bar'\n                raise Exception(\"unexpected path %r\" % path)\n\n            def get_content_size(self):\n                if self.absolute_path == 'CustomStaticFileTest:foo.txt':\n                    return 3\n                raise Exception(\"unexpected path %r\" % self.absolute_path)\n\n            def get_modified_time(self):\n                return None\n\n            @classmethod\n            def get_version(cls, settings, path):\n                return \"42\"\n\n        class StaticUrlHandler(RequestHandler):\n            def get(self, path):\n                self.write(self.static_url(path))\n\n        self.static_handler_class = MyStaticFileHandler\n\n        return [(\"/static_url/(.*)\", StaticUrlHandler)]\n\n    def get_app_kwargs(self):\n        return dict(static_path=\"dummy\",\n                    static_handler_class=self.static_handler_class)\n\n    def test_serve(self):\n        response = self.fetch(\"/static/foo.42.txt\")\n        self.assertEqual(response.body, b\"bar\")\n\n    def test_static_url(self):\n        with ExpectLog(gen_log, \"Could not open static file\", required=False):\n            response = self.fetch(\"/static_url/foo.txt\")\n            self.assertEqual(response.body, b\"/static/foo.42.txt\")\n\n\n@wsgi_safe\nclass HostMatchingTest(WebTestCase):\n    class Handler(RequestHandler):\n        def initialize(self, reply):\n            self.reply = reply\n\n        def get(self):\n            self.write(self.reply)\n\n    def get_handlers(self):\n        return [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"wildcard\"})]\n\n    def test_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n        self.app.add_handlers(\"www.e.*e.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[3]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"wildcard\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.code, 404)\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.example.com'})\n        self.assertEqual(response.body, b\"[2]\")\n        response = self.fetch(\"/baz\", headers={'Host': 'www.exe.com'})\n        self.assertEqual(response.body, b\"[3]\")\n\n\n@wsgi_safe\nclass DefaultHostMatchingTest(WebTestCase):\n    def get_handlers(self):\n        return []\n\n    def get_app_kwargs(self):\n        return {'default_host': \"www.example.com\"}\n\n    def test_default_host_matching(self):\n        self.app.add_handlers(\"www.example.com\",\n                              [(\"/foo\", HostMatchingTest.Handler, {\"reply\": \"[0]\"})])\n        self.app.add_handlers(r\"www\\.example\\.com\",\n                              [(\"/bar\", HostMatchingTest.Handler, {\"reply\": \"[1]\"})])\n        self.app.add_handlers(\"www.test.com\",\n                              [(\"/baz\", HostMatchingTest.Handler, {\"reply\": \"[2]\"})])\n\n        response = self.fetch(\"/foo\")\n        self.assertEqual(response.body, b\"[0]\")\n        response = self.fetch(\"/bar\")\n        self.assertEqual(response.body, b\"[1]\")\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.code, 404)\n\n        response = self.fetch(\"/foo\", headers={\"X-Real-Ip\": \"127.0.0.1\"})\n        self.assertEqual(response.code, 404)\n\n        self.app.default_host = \"www.test.com\"\n\n        response = self.fetch(\"/baz\")\n        self.assertEqual(response.body, b\"[2]\")\n\n\n@wsgi_safe\nclass NamedURLSpecGroupsTest(WebTestCase):\n    def get_handlers(self):\n        class EchoHandler(RequestHandler):\n            def get(self, path):\n                self.write(path)\n\n        return [(\"/str/(?P<path>.*)\", EchoHandler),\n                (u\"/unicode/(?P<path>.*)\", EchoHandler)]\n\n    def test_named_urlspec_groups(self):\n        response = self.fetch(\"/str/foo\")\n        self.assertEqual(response.body, b\"foo\")\n\n        response = self.fetch(\"/unicode/bar\")\n        self.assertEqual(response.body, b\"bar\")\n\n\n@wsgi_safe\nclass ClearHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"h1\", \"foo\")\n            self.set_header(\"h2\", \"bar\")\n            self.clear_header(\"h1\")\n            self.clear_header(\"nonexistent\")\n\n    def test_clear_header(self):\n        response = self.fetch(\"/\")\n        self.assertTrue(\"h1\" not in response.headers)\n        self.assertEqual(response.headers[\"h2\"], \"bar\")\n\n\nclass Header204Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(204)\n            self.finish()\n\n    def test_204_headers(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 204)\n        self.assertNotIn(\"Content-Length\", response.headers)\n        self.assertNotIn(\"Transfer-Encoding\", response.headers)\n\n\n@wsgi_safe\nclass Header304Test(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_header(\"Content-Language\", \"en_US\")\n            self.write(\"hello\")\n\n    def test_304_headers(self):\n        response1 = self.fetch('/')\n        self.assertEqual(response1.headers[\"Content-Length\"], \"5\")\n        self.assertEqual(response1.headers[\"Content-Language\"], \"en_US\")\n\n        response2 = self.fetch('/', headers={\n            'If-None-Match': response1.headers[\"Etag\"]})\n        self.assertEqual(response2.code, 304)\n        self.assertTrue(\"Content-Length\" not in response2.headers)\n        self.assertTrue(\"Content-Language\" not in response2.headers)\n        # Not an entity header, but should not be added to 304s by chunking\n        self.assertTrue(\"Transfer-Encoding\" not in response2.headers)\n\n\n@wsgi_safe\nclass StatusReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            reason = self.request.arguments.get('reason', [])\n            self.set_status(int(self.get_argument('code')),\n                            reason=reason[0] if reason else None)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_status(self):\n        response = self.fetch(\"/?code=304\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Not Modified\")\n        response = self.fetch(\"/?code=304&reason=Foo\")\n        self.assertEqual(response.code, 304)\n        self.assertEqual(response.reason, \"Foo\")\n        response = self.fetch(\"/?code=682&reason=Bar\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Bar\")\n        response = self.fetch(\"/?code=682\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Unknown\")\n\n\n@wsgi_safe\nclass DateHeaderTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(\"hello\")\n\n    def test_date_header(self):\n        response = self.fetch('/')\n        header_date = datetime.datetime(\n            *email.utils.parsedate(response.headers['Date'])[:6])\n        self.assertTrue(header_date - datetime.datetime.utcnow() <\n                        datetime.timedelta(seconds=2))\n\n\n@wsgi_safe\nclass RaiseWithReasonTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            raise HTTPError(682, reason=\"Foo\")\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't expose the reason string\n        return SimpleAsyncHTTPClient()\n\n    def test_raise_with_reason(self):\n        response = self.fetch(\"/\")\n        self.assertEqual(response.code, 682)\n        self.assertEqual(response.reason, \"Foo\")\n        self.assertIn(b'682: Foo', response.body)\n\n    def test_httperror_str(self):\n        self.assertEqual(str(HTTPError(682, reason=\"Foo\")), \"HTTP 682: Foo\")\n\n    def test_httperror_str_from_httputil(self):\n        self.assertEqual(str(HTTPError(682)), \"HTTP 682: Unknown\")\n\n\n@wsgi_safe\nclass ErrorHandlerXSRFTest(WebTestCase):\n    def get_handlers(self):\n        # note that if the handlers list is empty we get the default_host\n        # redirect fallback instead of a 404, so test with both an\n        # explicitly defined error handler and an implicit 404.\n        return [('/error', ErrorHandler, dict(status_code=417))]\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def test_error_xsrf(self):\n        response = self.fetch('/error', method='POST', body='')\n        self.assertEqual(response.code, 417)\n\n    def test_404_xsrf(self):\n        response = self.fetch('/404', method='POST', body='')\n        self.assertEqual(response.code, 404)\n\n\n@wsgi_safe\nclass GzipTestCase(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            for v in self.get_arguments('vary'):\n                self.add_header('Vary', v)\n            # Must write at least MIN_LENGTH bytes to activate compression.\n            self.write('hello world' + ('!' * GZipContentEncoding.MIN_LENGTH))\n\n    def get_app_kwargs(self):\n        return dict(\n            gzip=True,\n            static_path=os.path.join(os.path.dirname(__file__), 'static'))\n\n    def assert_compressed(self, response):\n        # simple_httpclient renames the content-encoding header;\n        # curl_httpclient doesn't.\n        self.assertEqual(\n            response.headers.get(\n                'Content-Encoding',\n                response.headers.get('X-Consumed-Content-Encoding')),\n            'gzip')\n\n    def test_gzip(self):\n        response = self.fetch('/')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_static(self):\n        # The streaming responses in StaticFileHandler have subtle\n        # interactions with the gzip output so test this case separately.\n        response = self.fetch('/robots.txt')\n        self.assert_compressed(response)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_gzip_not_requested(self):\n        response = self.fetch('/', use_gzip=False)\n        self.assertNotIn('Content-Encoding', response.headers)\n        self.assertEqual(response.headers['Vary'], 'Accept-Encoding')\n\n    def test_vary_already_present(self):\n        response = self.fetch('/?vary=Accept-Language')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Accept-Encoding'])\n\n    def test_vary_already_present_multiple(self):\n        # Regression test for https://github.com/tornadoweb/tornado/issues/1670\n        response = self.fetch('/?vary=Accept-Language&vary=Cookie')\n        self.assert_compressed(response)\n        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],\n                         ['Accept-Language', 'Cookie', 'Accept-Encoding'])\n\n\n@wsgi_safe\nclass PathArgsInPrepareTest(WebTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.write(dict(args=self.path_args, kwargs=self.path_kwargs))\n\n        def get(self, path):\n            assert path == 'foo'\n            self.finish()\n\n    def get_handlers(self):\n        return [('/pos/(.*)', self.Handler),\n                ('/kw/(?P<path>.*)', self.Handler)]\n\n    def test_pos(self):\n        response = self.fetch('/pos/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': ['foo'], 'kwargs': {}})\n\n    def test_kw(self):\n        response = self.fetch('/kw/foo')\n        response.rethrow()\n        data = json_decode(response.body)\n        self.assertEqual(data, {'args': [], 'kwargs': {'path': 'foo'}})\n\n\n@wsgi_safe\nclass ClearAllCookiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.clear_all_cookies()\n            self.write('ok')\n\n    def test_clear_all_cookies(self):\n        response = self.fetch('/', headers={'Cookie': 'foo=bar; baz=xyzzy'})\n        set_cookies = sorted(response.headers.get_list('Set-Cookie'))\n        # Python 3.5 sends 'baz=\"\";'; older versions use 'baz=;'\n        self.assertTrue(set_cookies[0].startswith('baz=;') or\n                        set_cookies[0].startswith('baz=\"\";'))\n        self.assertTrue(set_cookies[1].startswith('foo=;') or\n                        set_cookies[1].startswith('foo=\"\";'))\n\n\nclass PermissionError(Exception):\n    pass\n\n\n@wsgi_safe\nclass ExceptionHandlerTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            exc = self.get_argument('exc')\n            if exc == 'http':\n                raise HTTPError(410, \"no longer here\")\n            elif exc == 'zero':\n                1 / 0\n            elif exc == 'permission':\n                raise PermissionError('not allowed')\n\n        def write_error(self, status_code, **kwargs):\n            if 'exc_info' in kwargs:\n                typ, value, tb = kwargs['exc_info']\n                if isinstance(value, PermissionError):\n                    self.set_status(403)\n                    self.write('PermissionError')\n                    return\n            RequestHandler.write_error(self, status_code, **kwargs)\n\n        def log_exception(self, typ, value, tb):\n            if isinstance(value, PermissionError):\n                app_log.warning('custom logging for PermissionError: %s',\n                                value.args[0])\n            else:\n                RequestHandler.log_exception(self, typ, value, tb)\n\n    def test_http_error(self):\n        # HTTPErrors are logged as warnings with no stack trace.\n        # TODO: extend ExpectLog to test this more precisely\n        with ExpectLog(gen_log, '.*no longer here'):\n            response = self.fetch('/?exc=http')\n            self.assertEqual(response.code, 410)\n\n    def test_unknown_error(self):\n        # Unknown errors are logged as errors with a stack trace.\n        with ExpectLog(app_log, 'Uncaught exception'):\n            response = self.fetch('/?exc=zero')\n            self.assertEqual(response.code, 500)\n\n    def test_known_error(self):\n        # log_exception can override logging behavior, and write_error\n        # can override the response.\n        with ExpectLog(app_log,\n                       'custom logging for PermissionError: not allowed'):\n            response = self.fetch('/?exc=permission')\n            self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass BuggyLoggingTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            1 / 0\n\n        def log_exception(self, typ, value, tb):\n            1 / 0\n\n    def test_buggy_log_exception(self):\n        # Something gets logged even though the application's\n        # logger is broken.\n        with ExpectLog(app_log, '.*'):\n            self.fetch('/')\n\n\n@wsgi_safe\nclass UIMethodUIModuleTest(SimpleHandlerTestCase):\n    \"\"\"Test that UI methods and modules are created correctly and\n    associated with the handler.\n    \"\"\"\n    class Handler(RequestHandler):\n        def get(self):\n            self.render('foo.html')\n\n        def value(self):\n            return self.get_argument(\"value\")\n\n    def get_app_kwargs(self):\n        def my_ui_method(handler, x):\n            return \"In my_ui_method(%s) with handler value %s.\" % (\n                x, handler.value())\n\n        class MyModule(UIModule):\n            def render(self, x):\n                return \"In MyModule(%s) with handler value %s.\" % (\n                    x, self.handler.value())\n\n        loader = DictLoader({\n            'foo.html': '{{ my_ui_method(42) }} {% module MyModule(123) %}',\n        })\n        return dict(template_loader=loader,\n                    ui_methods={'my_ui_method': my_ui_method},\n                    ui_modules={'MyModule': MyModule})\n\n    def tearDown(self):\n        super(UIMethodUIModuleTest, self).tearDown()\n        # TODO: fix template loader caching so this isn't necessary.\n        RequestHandler._template_loaders.clear()\n\n    def test_ui_method(self):\n        response = self.fetch('/?value=asdf')\n        self.assertEqual(response.body,\n                         b'In my_ui_method(42) with handler value asdf. '\n                         b'In MyModule(123) with handler value asdf.')\n\n\n@wsgi_safe\nclass GetArgumentErrorTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            try:\n                self.get_argument('foo')\n                self.write({})\n            except MissingArgumentError as e:\n                self.write({'arg_name': e.arg_name,\n                            'log_message': e.log_message})\n\n    def test_catch_error(self):\n        response = self.fetch('/')\n        self.assertEqual(json_decode(response.body),\n                         {'arg_name': 'foo',\n                          'log_message': 'Missing argument foo'})\n\n\nclass MultipleExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        exc_count = 0\n\n        @asynchronous\n        def get(self):\n            from tornado.ioloop import IOLoop\n            IOLoop.current().add_callback(lambda: 1 / 0)\n            IOLoop.current().add_callback(lambda: 1 / 0)\n\n        def log_exception(self, typ, value, tb):\n            MultipleExceptionTest.Handler.exc_count += 1\n\n    def test_multi_exception(self):\n        # This test verifies that multiple exceptions raised into the same\n        # ExceptionStackContext do not generate extraneous log entries\n        # due to \"Cannot send error response after headers written\".\n        # log_exception is called, but it does not proceed to send_error.\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        response = self.fetch('/')\n        self.assertEqual(response.code, 500)\n        # Each of our two requests generated two exceptions, we should have\n        # seen at least three of them by now (the fourth may still be\n        # in the queue).\n        self.assertGreater(MultipleExceptionTest.Handler.exc_count, 2)\n\n\n@wsgi_safe\nclass SetLazyPropertiesTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.current_user = 'Ben'\n            self.locale = locale.get('en_US')\n\n        def get_user_locale(self):\n            raise NotImplementedError()\n\n        def get_current_user(self):\n            raise NotImplementedError()\n\n        def get(self):\n            self.write('Hello %s (%s)' % (self.current_user, self.locale.code))\n\n    def test_set_properties(self):\n        # Ensure that current_user can be assigned to normally for apps\n        # that want to forgo the lazy get_current_user property\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'Hello Ben (en_US)')\n\n\n@wsgi_safe\nclass GetCurrentUserTest(WebTestCase):\n    def get_app_kwargs(self):\n        class WithoutUserModule(UIModule):\n            def render(self):\n                return ''\n\n        class WithUserModule(UIModule):\n            def render(self):\n                return str(self.current_user)\n\n        loader = DictLoader({\n            'without_user.html': '',\n            'with_user.html': '{{ current_user }}',\n            'without_user_module.html': '{% module WithoutUserModule() %}',\n            'with_user_module.html': '{% module WithUserModule() %}',\n        })\n        return dict(template_loader=loader,\n                    ui_modules={'WithUserModule': WithUserModule,\n                                'WithoutUserModule': WithoutUserModule})\n\n    def tearDown(self):\n        super(GetCurrentUserTest, self).tearDown()\n        RequestHandler._template_loaders.clear()\n\n    def get_handlers(self):\n        class CurrentUserHandler(RequestHandler):\n            def prepare(self):\n                self.has_loaded_current_user = False\n\n            def get_current_user(self):\n                self.has_loaded_current_user = True\n                return ''\n\n        class WithoutUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('without_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserHandler(CurrentUserHandler):\n            def get(self):\n                self.render_string('with_user.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class CurrentUserModuleHandler(CurrentUserHandler):\n            def get_template_namespace(self):\n                # If RequestHandler.get_template_namespace is called, then\n                # get_current_user is evaluated. Until #820 is fixed, this\n                # is a small hack to circumvent the issue.\n                return self.ui\n\n        class WithoutUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('without_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        class WithUserModuleHandler(CurrentUserModuleHandler):\n            def get(self):\n                self.render_string('with_user_module.html')\n                self.finish(str(self.has_loaded_current_user))\n\n        return [('/without_user', WithoutUserHandler),\n                ('/with_user', WithUserHandler),\n                ('/without_user_module', WithoutUserModuleHandler),\n                ('/with_user_module', WithUserModuleHandler)]\n\n    @unittest.skip('needs fix')\n    def test_get_current_user_is_lazy(self):\n        # TODO: Make this test pass. See #820.\n        response = self.fetch('/without_user')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_works(self):\n        response = self.fetch('/with_user')\n        self.assertEqual(response.body, b'True')\n\n    def test_get_current_user_from_ui_module_is_lazy(self):\n        response = self.fetch('/without_user_module')\n        self.assertEqual(response.body, b'False')\n\n    def test_get_current_user_from_ui_module_works(self):\n        response = self.fetch('/with_user_module')\n        self.assertEqual(response.body, b'True')\n\n\n@wsgi_safe\nclass UnimplementedHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        pass\n\n    def test_unimplemented_standard_methods(self):\n        for method in ['HEAD', 'GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.code, 405)\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.code, 405)\n\n\nclass UnimplementedNonStandardMethodsTest(SimpleHandlerTestCase):\n    # wsgiref.validate complains about unknown methods in a way that makes\n    # this test not wsgi_safe.\n    class Handler(RequestHandler):\n        def other(self):\n            # Even though this method exists, it won't get called automatically\n            # because it is not in SUPPORTED_METHODS.\n            self.write('other')\n\n    def test_unimplemented_patch(self):\n        # PATCH is recently standardized; Tornado supports it by default\n        # but wsgiref.validate doesn't like it.\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.code, 405)\n\n    def test_unimplemented_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.code, 405)\n\n\n@wsgi_safe\nclass AllHTTPMethodsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def method(self):\n            self.write(self.request.method)\n\n        get = delete = options = post = put = method\n\n    def test_standard_methods(self):\n        response = self.fetch('/', method='HEAD')\n        self.assertEqual(response.body, b'')\n        for method in ['GET', 'DELETE', 'OPTIONS']:\n            response = self.fetch('/', method=method)\n            self.assertEqual(response.body, utf8(method))\n        for method in ['POST', 'PUT']:\n            response = self.fetch('/', method=method, body=b'')\n            self.assertEqual(response.body, utf8(method))\n\n\nclass PatchMethodTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        SUPPORTED_METHODS = RequestHandler.SUPPORTED_METHODS + ('OTHER',)\n\n        def patch(self):\n            self.write('patch')\n\n        def other(self):\n            self.write('other')\n\n    def test_patch(self):\n        response = self.fetch('/', method='PATCH', body=b'')\n        self.assertEqual(response.body, b'patch')\n\n    def test_other(self):\n        response = self.fetch('/', method='OTHER',\n                              allow_nonstandard_methods=True)\n        self.assertEqual(response.body, b'other')\n\n\n@wsgi_safe\nclass FinishInPrepareTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def prepare(self):\n            self.finish('done')\n\n        def get(self):\n            # It's difficult to assert for certain that a method did not\n            # or will not be called in an asynchronous context, but this\n            # will be logged noisily if it is reached.\n            raise Exception('should not reach this method')\n\n    def test_finish_in_prepare(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b'done')\n\n\n@wsgi_safe\nclass Default404Test(WebTestCase):\n    def get_handlers(self):\n        # If there are no handlers at all a default redirect handler gets added.\n        return [('/foo', RequestHandler)]\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body,\n                         b'<html><title>404: Not Found</title>'\n                         b'<body>404: Not Found</body></html>')\n\n\n@wsgi_safe\nclass Custom404Test(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        class Custom404Handler(RequestHandler):\n            def get(self):\n                self.set_status(404)\n                self.write('custom 404 response')\n\n        return dict(default_handler_class=Custom404Handler)\n\n    def test_404(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 404)\n        self.assertEqual(response.body, b'custom 404 response')\n\n\n@wsgi_safe\nclass DefaultHandlerArgumentsTest(WebTestCase):\n    def get_handlers(self):\n        return [('/foo', RequestHandler)]\n\n    def get_app_kwargs(self):\n        return dict(default_handler_class=ErrorHandler,\n                    default_handler_args=dict(status_code=403))\n\n    def test_403(self):\n        response = self.fetch('/')\n        self.assertEqual(response.code, 403)\n\n\n@wsgi_safe\nclass HandlerByNameTest(WebTestCase):\n    def get_handlers(self):\n        # All three are equivalent.\n        return [('/hello1', HelloHandler),\n                ('/hello2', 'tornado.test.web_test.HelloHandler'),\n                url('/hello3', 'tornado.test.web_test.HelloHandler'),\n                ]\n\n    def test_handler_by_name(self):\n        resp = self.fetch('/hello1')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello2')\n        self.assertEqual(resp.body, b'hello')\n        resp = self.fetch('/hello3')\n        self.assertEqual(resp.body, b'hello')\n\n\nclass StreamingRequestBodyTest(WebTestCase):\n    def get_handlers(self):\n        @stream_request_body\n        class StreamingBodyHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def prepare(self):\n                self.test.prepared.set_result(None)\n\n            def data_received(self, data):\n                self.test.data.set_result(data)\n\n            def get(self):\n                self.test.finished.set_result(None)\n                self.write({})\n\n        @stream_request_body\n        class EarlyReturnHandler(RequestHandler):\n            def prepare(self):\n                # If we finish the response in prepare, it won't continue to\n                # the (non-existent) data_received.\n                raise HTTPError(401)\n\n        @stream_request_body\n        class CloseDetectionHandler(RequestHandler):\n            def initialize(self, test):\n                self.test = test\n\n            def on_connection_close(self):\n                super(CloseDetectionHandler, self).on_connection_close()\n                self.test.close_future.set_result(None)\n\n        return [('/stream_body', StreamingBodyHandler, dict(test=self)),\n                ('/early_return', EarlyReturnHandler),\n                ('/close_detection', CloseDetectionHandler, dict(test=self))]\n\n    def connect(self, url, connection_close):\n        # Use a raw connection so we can control the sending of data.\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)\n        s.connect((\"127.0.0.1\", self.get_http_port()))\n        stream = IOStream(s)\n        stream.write(b\"GET \" + url + b\" HTTP/1.1\\r\\n\")\n        if connection_close:\n            stream.write(b\"Connection: close\\r\\n\")\n        stream.write(b\"Transfer-Encoding: chunked\\r\\n\\r\\n\")\n        return stream\n\n    @gen_test\n    def test_streaming_body(self):\n        self.prepared = Future()\n        self.data = Future()\n        self.finished = Future()\n\n        stream = self.connect(b\"/stream_body\", connection_close=True)\n        yield self.prepared\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        # Ensure the first chunk is received before we send the second.\n        data = yield self.data\n        self.assertEqual(data, b\"asdf\")\n        self.data = Future()\n        stream.write(b\"4\\r\\nqwer\\r\\n\")\n        data = yield self.data\n        self.assertEquals(data, b\"qwer\")\n        stream.write(b\"0\\r\\n\")\n        yield self.finished\n        data = yield gen.Task(stream.read_until_close)\n        # This would ideally use an HTTP1Connection to read the response.\n        self.assertTrue(data.endswith(b\"{}\"))\n        stream.close()\n\n    @gen_test\n    def test_early_return(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_early_return_with_data(self):\n        stream = self.connect(b\"/early_return\", connection_close=False)\n        stream.write(b\"4\\r\\nasdf\\r\\n\")\n        data = yield gen.Task(stream.read_until_close)\n        self.assertTrue(data.startswith(b\"HTTP/1.1 401\"))\n\n    @gen_test\n    def test_close_during_upload(self):\n        self.close_future = Future()\n        stream = self.connect(b\"/close_detection\", connection_close=False)\n        stream.close()\n        yield self.close_future\n\n\n# Each method in this handler returns a yieldable object and yields to the\n# IOLoop so the future is not immediately ready.  Ensure that the\n# yieldables are respected and no method is called before the previous\n# one has completed.\n@stream_request_body\nclass BaseFlowControlHandler(RequestHandler):\n    def initialize(self, test):\n        self.test = test\n        self.method = None\n        self.methods = []\n\n    @contextlib.contextmanager\n    def in_method(self, method):\n        if self.method is not None:\n            self.test.fail(\"entered method %s while in %s\" %\n                           (method, self.method))\n        self.method = method\n        self.methods.append(method)\n        try:\n            yield\n        finally:\n            self.method = None\n\n    @gen.coroutine\n    def prepare(self):\n        # Note that asynchronous prepare() does not block data_received,\n        # so we don't use in_method here.\n        self.methods.append('prepare')\n        yield gen.Task(IOLoop.current().add_callback)\n\n    @gen.coroutine\n    def post(self):\n        with self.in_method('post'):\n            yield gen.Task(IOLoop.current().add_callback)\n        self.write(dict(methods=self.methods))\n\n\nclass BaseStreamingRequestFlowControlTest(object):\n    def get_httpserver_options(self):\n        # Use a small chunk size so flow control is relevant even though\n        # all the data arrives at once.\n        return dict(chunk_size=10, decompress_request=True)\n\n    def get_http_client(self):\n        # simple_httpclient only: curl doesn't support body_producer.\n        return SimpleAsyncHTTPClient()\n\n    # Test all the slightly different code paths for fixed, chunked, etc bodies.\n    def test_flow_control_fixed_body(self):\n        response = self.fetch('/', body='abcdefghijklmnopqrstuvwxyz',\n                              method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_chunked_body(self):\n        chunks = [b'abcd', b'efgh', b'ijkl']\n\n        @gen.coroutine\n        def body_producer(write):\n            for i in chunks:\n                yield write(i)\n        response = self.fetch('/', body_producer=body_producer, method='POST')\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n    def test_flow_control_compressed_body(self):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(b'abcdefghijklmnopqrstuvwxyz')\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        response = self.fetch('/', body=compressed_body, method='POST',\n                              headers={'Content-Encoding': 'gzip'})\n        response.rethrow()\n        self.assertEqual(json_decode(response.body),\n                         dict(methods=['prepare', 'data_received',\n                                       'data_received', 'data_received',\n                                       'post']))\n\n\nclass DecoratedStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class DecoratedFlowControlHandler(BaseFlowControlHandler):\n            @gen.coroutine\n            def data_received(self, data):\n                with self.in_method('data_received'):\n                    yield gen.Task(IOLoop.current().add_callback)\n        return [('/', DecoratedFlowControlHandler, dict(test=self))]\n\n\n@skipBefore35\nclass NativeStreamingRequestFlowControlTest(\n        BaseStreamingRequestFlowControlTest,\n        WebTestCase):\n    def get_handlers(self):\n        class NativeFlowControlHandler(BaseFlowControlHandler):\n            data_received = exec_test(globals(), locals(), \"\"\"\n            async def data_received(self, data):\n                with self.in_method('data_received'):\n                    await gen.Task(IOLoop.current().add_callback)\n            \"\"\")[\"data_received\"]\n        return [('/', NativeFlowControlHandler, dict(test=self))]\n\n\n@wsgi_safe\nclass IncorrectContentLengthTest(SimpleHandlerTestCase):\n    def get_handlers(self):\n        test = self\n        self.server_error = None\n\n        # Manually set a content-length that doesn't match the actual content.\n        class TooHigh(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"42\")\n                try:\n                    self.finish(\"ok\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        class TooLow(RequestHandler):\n            def get(self):\n                self.set_header(\"Content-Length\", \"2\")\n                try:\n                    self.finish(\"hello\")\n                except Exception as e:\n                    test.server_error = e\n                    raise\n\n        return [('/high', TooHigh),\n                ('/low', TooLow)]\n\n    def test_content_length_too_high(self):\n        # When the content-length is too high, the connection is simply\n        # closed without completing the response.  An error is logged on\n        # the server.\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/high\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write 40 bytes less than Content-Length\")\n\n    def test_content_length_too_low(self):\n        # When the content-length is too low, the connection is closed\n        # without writing the last chunk, so the client never sees the request\n        # complete (which would be a framing error).\n        with ExpectLog(app_log, \"(Uncaught exception|Exception in callback)\"):\n            with ExpectLog(gen_log,\n                           \"(Cannot send error response after headers written\"\n                           \"|Failed to flush partial response)\"):\n                response = self.fetch(\"/low\")\n        self.assertEqual(response.code, 599)\n        self.assertEqual(str(self.server_error),\n                         \"Tried to write more data than Content-Length\")\n\n\nclass ClientCloseTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            if self.request.version.startswith('HTTP/1'):\n                # Simulate a connection closed by the client during\n                # request processing.  The client will see an error, but the\n                # server should respond gracefully (without logging errors\n                # because we were unable to write out as many bytes as\n                # Content-Length said we would)\n                self.request.connection.stream.close()\n                self.write('hello')\n            else:\n                # TODO: add a HTTP2-compatible version of this test.\n                self.write('requires HTTP/1.x')\n\n    def test_client_close(self):\n        response = self.fetch('/')\n        if response.body == b'requires HTTP/1.x':\n            self.skipTest('requires HTTP/1.x')\n        self.assertEqual(response.code, 599)\n\n\nclass SignedValueTest(unittest.TestCase):\n    SECRET = \"It's a secret to everybody\"\n    SECRET_DICT = {0: \"asdfbasdf\", 1: \"12312312\", 2: \"2342342\"}\n\n    def past(self):\n        return self.present() - 86400 * 32\n\n    def present(self):\n        return 1300000000\n\n    def test_known_values(self):\n        signed_v1 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=1, clock=self.present)\n        self.assertEqual(\n            signed_v1,\n            b\"dmFsdWU=|1300000000|31c934969f53e48164c50768b40cbd7e2daaaa4f\")\n\n        signed_v2 = create_signed_value(SignedValueTest.SECRET, \"key\", \"value\",\n                                        version=2, clock=self.present)\n        self.assertEqual(\n            signed_v2,\n            b\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n            b\"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\")\n\n        signed_default = create_signed_value(SignedValueTest.SECRET,\n                                             \"key\", \"value\", clock=self.present)\n        self.assertEqual(signed_default, signed_v2)\n\n        decoded_v1 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v1, min_version=1,\n                                         clock=self.present)\n        self.assertEqual(decoded_v1, b\"value\")\n\n        decoded_v2 = decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                         signed_v2, min_version=2,\n                                         clock=self.present)\n        self.assertEqual(decoded_v2, b\"value\")\n\n    def test_name_swap(self):\n        signed1 = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                      clock=self.present)\n        signed2 = create_signed_value(SignedValueTest.SECRET, \"key2\", \"value\",\n                                      clock=self.present)\n        # Try decoding each string with the other's \"name\"\n        decoded1 = decode_signed_value(SignedValueTest.SECRET, \"key2\", signed1,\n                                       clock=self.present)\n        self.assertIs(decoded1, None)\n        decoded2 = decode_signed_value(SignedValueTest.SECRET, \"key1\", signed2,\n                                       clock=self.present)\n        self.assertIs(decoded2, None)\n\n    def test_expired(self):\n        signed = create_signed_value(SignedValueTest.SECRET, \"key1\", \"value\",\n                                     clock=self.past)\n        decoded_past = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                           signed, clock=self.past)\n        self.assertEqual(decoded_past, b\"value\")\n        decoded_present = decode_signed_value(SignedValueTest.SECRET, \"key1\",\n                                              signed, clock=self.present)\n        self.assertIs(decoded_present, None)\n\n    def test_payload_tampering(self):\n        # These cookies are variants of the one in test_known_values.\n        sig = \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"\n\n        def validate(prefix):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # Change key version\n        self.assertFalse(validate(\"2|1:1|10:1300000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too short)\n        self.assertFalse(validate(\"2|1:0|10:130000000|3:key|8:dmFsdWU=|\"))\n        # length mismatch (field too long)\n        self.assertFalse(validate(\"2|1:0|10:1300000000|3:keey|8:dmFsdWU=|\"))\n\n    def test_signature_tampering(self):\n        prefix = \"2|1:0|10:1300000000|3:key|8:dmFsdWU=|\"\n\n        def validate(sig):\n            return (b'value' ==\n                    decode_signed_value(SignedValueTest.SECRET, \"key\",\n                                        prefix + sig, clock=self.present))\n        self.assertTrue(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # All zeros\n        self.assertFalse(validate(\"0\" * 32))\n        # Change one character\n        self.assertFalse(validate(\n            \"4d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e152\"))\n        # Change another character\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e153\"))\n        # Truncate\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e15\"))\n        # Lengthen\n        self.assertFalse(validate(\n            \"3d4e60b996ff9c5d5788e333a0cba6f238a22c6c0f94788870e1a9ecd482e1538\"))\n\n    def test_non_ascii(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET, \"key\", value,\n                                     clock=self.present)\n        decoded = decode_signed_value(SignedValueTest.SECRET, \"key\", signed,\n                                      clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_read_write_non_default_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        decoded = decode_signed_value(SignedValueTest.SECRET_DICT,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(value, decoded)\n\n    def test_key_versioning_invalid_key(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=0)\n        newkeys = SignedValueTest.SECRET_DICT.copy()\n        newkeys.pop(0)\n        decoded = decode_signed_value(newkeys,\n                                      \"key\", signed, clock=self.present)\n        self.assertEqual(None, decoded)\n\n    def test_key_version_retrieval(self):\n        value = b\"\\xe9\"\n        signed = create_signed_value(SignedValueTest.SECRET_DICT,\n                                     \"key\", value, clock=self.present,\n                                     key_version=1)\n        key_version = get_signature_key_version(signed)\n        self.assertEqual(1, key_version)\n\n\n@wsgi_safe\nclass XSRFTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            version = int(self.get_argument(\"version\", \"2\"))\n            # This would be a bad idea in a real app, but in this test\n            # it's fine.\n            self.settings[\"xsrf_cookie_version\"] = version\n            self.write(self.xsrf_token)\n\n        def post(self):\n            self.write(\"ok\")\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True)\n\n    def setUp(self):\n        super(XSRFTest, self).setUp()\n        self.xsrf_token = self.get_token()\n\n    def get_token(self, old_token=None, version=None):\n        if old_token is not None:\n            headers = self.cookie_headers(old_token)\n        else:\n            headers = None\n        response = self.fetch(\n            \"/\" if version is None else (\"/?version=%d\" % version),\n            headers=headers)\n        response.rethrow()\n        return native_str(response.body)\n\n    def cookie_headers(self, token=None):\n        if token is None:\n            token = self.xsrf_token\n        return {\"Cookie\": \"_xsrf=\" + token}\n\n    def test_xsrf_fail_no_token(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\"/\", method=\"POST\", body=b\"\")\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_body_no_cookie(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_argument_invalid_format(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument has invalid format\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(),\n                body=urllib_parse.urlencode(dict(_xsrf='3|')))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_invalid_format(self):\n        with ExpectLog(gen_log, \".*XSRF cookie does not match POST\"):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                headers=self.cookie_headers(token='3|'),\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)))\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_fail_cookie_no_body(self):\n        with ExpectLog(gen_log, \".*'_xsrf' argument missing\"):\n            response = self.fetch(\n                \"/\", method=\"POST\", body=b\"\",\n                headers=self.cookie_headers())\n        self.assertEqual(response.code, 403)\n\n    def test_xsrf_success_short_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='deadbeef')),\n            headers=self.cookie_headers(token='deadbeef'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_non_hex_token(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf='xoxo')),\n            headers=self.cookie_headers(token='xoxo'))\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_post_body(self):\n        response = self.fetch(\n            \"/\", method=\"POST\",\n            body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_query_string(self):\n        response = self.fetch(\n            \"/?\" + urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n            method=\"POST\", body=b\"\",\n            headers=self.cookie_headers())\n        self.assertEqual(response.code, 200)\n\n    def test_xsrf_success_header(self):\n        response = self.fetch(\"/\", method=\"POST\", body=b\"\",\n                              headers=dict({\"X-Xsrftoken\": self.xsrf_token},  # type: ignore\n                                           **self.cookie_headers()))\n        self.assertEqual(response.code, 200)\n\n    def test_distinct_tokens(self):\n        # Every request gets a distinct token.\n        NUM_TOKENS = 10\n        tokens = set()\n        for i in range(NUM_TOKENS):\n            tokens.add(self.get_token())\n        self.assertEqual(len(tokens), NUM_TOKENS)\n\n    def test_cross_user(self):\n        token2 = self.get_token()\n        # Each token can be used to authenticate its own request.\n        for token in (self.xsrf_token, token2):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        # Sending one in the cookie and the other in the body is not allowed.\n        for cookie_token, body_token in ((self.xsrf_token, token2),\n                                         (token2, self.xsrf_token)):\n            with ExpectLog(gen_log, '.*XSRF cookie does not match POST'):\n                response = self.fetch(\n                    \"/\", method=\"POST\",\n                    body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                    headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 403)\n\n    def test_refresh_token(self):\n        token = self.xsrf_token\n        tokens_seen = set([token])\n        # A user's token is stable over time.  Refreshing the page in one tab\n        # might update the cookie while an older tab still has the old cookie\n        # in its DOM.  Simulate this scenario by passing a constant token\n        # in the body and re-querying for the token.\n        for i in range(5):\n            token = self.get_token(token)\n            # Tokens are encoded uniquely each time\n            tokens_seen.add(token)\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=self.xsrf_token)),\n                headers=self.cookie_headers(token))\n            self.assertEqual(response.code, 200)\n        self.assertEqual(len(tokens_seen), 6)\n\n    def test_versioning(self):\n        # Version 1 still produces distinct tokens per request.\n        self.assertNotEqual(self.get_token(version=1),\n                            self.get_token(version=1))\n\n        # Refreshed v1 tokens are all identical.\n        v1_token = self.get_token(version=1)\n        for i in range(5):\n            self.assertEqual(self.get_token(v1_token, version=1), v1_token)\n\n        # Upgrade to a v2 version of the same token\n        v2_token = self.get_token(v1_token)\n        self.assertNotEqual(v1_token, v2_token)\n        # Each v1 token can map to many v2 tokens.\n        self.assertNotEqual(v2_token, self.get_token(v1_token))\n\n        # The tokens are cross-compatible.\n        for cookie_token, body_token in ((v1_token, v2_token),\n                                         (v2_token, v1_token)):\n            response = self.fetch(\n                \"/\", method=\"POST\",\n                body=urllib_parse.urlencode(dict(_xsrf=body_token)),\n                headers=self.cookie_headers(cookie_token))\n            self.assertEqual(response.code, 200)\n\n\n@wsgi_safe\nclass XSRFCookieKwargsTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(self.xsrf_token)\n\n    def get_app_kwargs(self):\n        return dict(xsrf_cookies=True,\n                    xsrf_cookie_kwargs=dict(httponly=True))\n\n    def test_xsrf_httponly(self):\n        response = self.fetch(\"/\")\n        self.assertIn('httponly;', response.headers['Set-Cookie'].lower())\n\n\n@wsgi_safe\nclass FinishExceptionTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.set_status(401)\n            self.set_header('WWW-Authenticate', 'Basic realm=\"something\"')\n            if self.get_argument('finish_value', ''):\n                raise Finish('authentication required')\n            else:\n                self.write('authentication required')\n                raise Finish()\n\n    def test_finish_exception(self):\n        for u in ['/', '/?finish_value=1']:\n            response = self.fetch(u)\n            self.assertEqual(response.code, 401)\n            self.assertEqual('Basic realm=\"something\"',\n                             response.headers.get('WWW-Authenticate'))\n            self.assertEqual(b'authentication required', response.body)\n\n\n@wsgi_safe\nclass DecoratorTest(WebTestCase):\n    def get_handlers(self):\n        class RemoveSlashHandler(RequestHandler):\n            @removeslash\n            def get(self):\n                pass\n\n        class AddSlashHandler(RequestHandler):\n            @addslash\n            def get(self):\n                pass\n\n        return [(\"/removeslash/\", RemoveSlashHandler),\n                (\"/addslash\", AddSlashHandler),\n                ]\n\n    def test_removeslash(self):\n        response = self.fetch(\"/removeslash/\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash\")\n\n        response = self.fetch(\"/removeslash/?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/removeslash?foo=bar\")\n\n    def test_addslash(self):\n        response = self.fetch(\"/addslash\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/\")\n\n        response = self.fetch(\"/addslash?foo=bar\", follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], \"/addslash/?foo=bar\")\n\n\n@wsgi_safe\nclass CacheTest(WebTestCase):\n    def get_handlers(self):\n        class EtagHandler(RequestHandler):\n            def get(self, computed_etag):\n                self.write(computed_etag)\n\n            def compute_etag(self):\n                return self._write_buffer[0]\n\n        return [\n            ('/etag/(.*)', EtagHandler)\n        ]\n\n    def test_wildcard_etag(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '*'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_strong_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_strong_etag_not_match(self):\n        computed_etag = '\"xyzzy\"'\n        etags = '\"xyzzy1\", \"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_weak_etag_match(self):\n        computed_etag = '\"xyzzy1\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_multiple_weak_etag_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 304)\n\n    def test_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy2\"'\n        etags = 'W/\"xyzzy1\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def test_multiple_weak_etag_not_match(self):\n        computed_etag = '\"xyzzy3\"'\n        etags = 'W/\"xyzzy1\", W/\"xyzzy2\"'\n        self._test_etag(computed_etag, etags, 200)\n\n    def _test_etag(self, computed_etag, etags, status_code):\n        response = self.fetch(\n            '/etag/' + computed_etag,\n            headers={'If-None-Match': etags}\n        )\n        self.assertEqual(response.code, status_code)\n\n\n@wsgi_safe\nclass RequestSummaryTest(SimpleHandlerTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            # remote_ip is optional, although it's set by\n            # both HTTPServer and WSGIAdapter.\n            # Clobber it to make sure it doesn't break logging.\n            self.request.remote_ip = None\n            self.finish(self._request_summary())\n\n    def test_missing_remote_ip(self):\n        resp = self.fetch(\"/\")\n        self.assertEqual(resp.body, b\"GET / (None)\")\n\n\nclass HTTPErrorTest(unittest.TestCase):\n    def test_copy(self):\n        e = HTTPError(403, reason=\"Go away\")\n        e2 = copy.copy(e)\n        self.assertIsNot(e, e2)\n        self.assertEqual(e.status_code, e2.status_code)\n        self.assertEqual(e.reason, e2.reason)\n\n\nclass ApplicationTest(AsyncTestCase):\n    def test_listen(self):\n        app = Application([])\n        server = app.listen(0, address='127.0.0.1')\n        server.stop()\n\n\nclass URLSpecReverseTest(unittest.TestCase):\n    def test_reverse(self):\n        self.assertEqual('/favicon.ico', url(r'/favicon\\.ico', None).reverse())\n        self.assertEqual('/favicon.ico', url(r'^/favicon\\.ico$', None).reverse())\n\n    def test_non_reversible(self):\n        # URLSpecs are non-reversible if they include non-constant\n        # regex features outside capturing groups. Currently, this is\n        # only strictly enforced for backslash-escaped character\n        # classes.\n        paths = [\n            r'^/api/v\\d+/foo/(\\w+)$',\n        ]\n        for path in paths:\n            # A URLSpec can still be created even if it cannot be reversed.\n            url_spec = url(path, None)\n            try:\n                result = url_spec.reverse()\n                self.fail(\"did not get expected exception when reversing %s. \"\n                          \"result: %s\" % (path, result))\n            except ValueError:\n                pass\n\n    def test_reverse_arguments(self):\n        self.assertEqual('/api/v1/foo/bar',\n                         url(r'^/api/v1/foo/(\\w+)$', None).reverse('bar'))\n\n\nclass RedirectHandlerTest(WebTestCase):\n    def get_handlers(self):\n        return [\n            ('/src', WebRedirectHandler, {'url': '/dst'}),\n            ('/src2', WebRedirectHandler, {'url': '/dst2?foo=bar'}),\n            (r'/(.*?)/(.*?)/(.*)', WebRedirectHandler, {'url': '/{1}/{0}/{2}'})]\n\n    def test_basic_redirect(self):\n        response = self.fetch('/src', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst')\n\n    def test_redirect_with_argument(self):\n        response = self.fetch('/src?foo=bar', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst?foo=bar')\n\n    def test_redirect_with_appending_argument(self):\n        response = self.fetch('/src2?foo2=bar2', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/dst2?foo=bar&foo2=bar2')\n\n    def test_redirect_pattern(self):\n        response = self.fetch('/a/b/c', follow_redirects=False)\n        self.assertEqual(response.code, 301)\n        self.assertEqual(response.headers['Location'], '/b/a/c')\n",
        "from __future__ import absolute_import, division, print_function\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport ssl\nimport sys\n\nfrom tornado.escape import to_unicode\nfrom tornado import gen\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders, ResponseStartLine\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.concurrent import Future\nfrom tornado.netutil import Resolver, bind_sockets\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler, RedirectHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import skipOnTravis, skipIfNoIPv6, refusing_port, unittest, skipBefore35, exec_test\nfrom tornado.web import RequestHandler, Application, asynchronous, url, stream_request_body\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        self.set_status(204)\n        self.finish()\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass NoContentLengthHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        if self.request.version.startswith('HTTP/1'):\n            # Emulate the old HTTP/1.0 behavior of returning a body with no\n            # content-length.  Tornado handles content-length at the framework\n            # level so we have to go around it.\n            stream = self.request.connection.detach()\n            stream.write(b\"HTTP/1.0 200 OK\\r\\n\\r\\n\"\n                         b\"hello\")\n            stream.close()\n        else:\n            self.finish('HTTP/1 required')\n\n\nclass EchoPostHandler(RequestHandler):\n    def post(self):\n        self.write(self.request.body)\n\n\n@stream_request_body\nclass RespondInPrepareHandler(RequestHandler):\n    def prepare(self):\n        self.set_status(403)\n        self.finish(\"forbidden\")\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n            url(\"/no_content_length\", NoContentLengthHandler),\n            url(\"/echo_post\", EchoPostHandler),\n            url(\"/respond_in_prepare\", RespondInPrepareHandler),\n            url(\"/redirect\", RedirectHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient() is\n                        SimpleAsyncHTTPClient())\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient() is not\n                        SimpleAsyncHTTPClient(force_instance=True))\n        # different IOLoops use different objects\n        with closing(IOLoop()) as io_loop2:\n            client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient))\n            self.assertTrue(client1 is not client2)\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        # Chunked encoding bypasses the MIN_LENGTH check.\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_connect_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 1.0\n\n        class TimeoutResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                return Future()  # never completes\n\n        with closing(self.create_client(resolver=TimeoutResolver())) as client:\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=timeout)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n            self.assertTrue(timeout_min < response.request_time < timeout_max,\n                            response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout while connecting\")\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        timeout = 0.1\n        timeout_min, timeout_max = 0.099, 0.15\n        if os.name == 'nt':\n            timeout = 0.5\n            timeout_min, timeout_max = 0.4, 0.6\n\n        response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(timeout_min < response.request_time < timeout_max,\n                        response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout during request\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @skipIfNoIPv6\n    def test_ipv6(self):\n        [sock] = bind_sockets(None, '::1', family=socket.AF_INET6)\n        port = sock.getsockname()[1]\n        self.http_server.add_socket(sock)\n        url = '%s://[::1]:%d/hello' % (self.get_protocol(), port)\n\n        # ipv6 is currently enabled by default but can be disabled\n        self.http_client.fetch(url, self.stop, allow_ipv6=False)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def xtest_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status shouldn't have a content-length\n        #\n        # Tests with a content-length header are included below\n        # in HTTP204NoContentTestCase.\n        self.assertNotIn(\"Content-Length\", response.headers)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^127.0.0.1:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        cleanup_func, port = refusing_port()\n        self.addCleanup(cleanup_func)\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://127.0.0.1:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            contains_errno = str(errno.ECONNREFUSED) in str(response.error)\n            if not contains_errno and hasattr(errno, \"WSAECONNREFUSED\"):\n                contains_errno = str(errno.WSAECONNREFUSED) in str(response.error)\n            self.assertTrue(contains_errno, response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n    def test_queue_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger'), self.stop,\n                         request_timeout=10)\n            # Wait for the trigger request to block, not complete.\n            self.wait()\n            client.fetch(self.get_url('/hello'), self.stop,\n                         connect_timeout=0.1)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(response.request_time < 1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout in request queue\")\n            self.triggers.popleft()()\n            self.wait()\n\n    def test_no_content_length(self):\n        response = self.fetch(\"/no_content_length\")\n        if response.body == b\"HTTP/1 required\":\n            self.skipTest(\"requires HTTP/1.x\")\n        else:\n            self.assertEquals(b\"hello\", response.body)\n\n    def sync_body_producer(self, write):\n        write(b'1234')\n        write(b'5678')\n\n    @gen.coroutine\n    def async_body_producer(self, write):\n        yield write(b'1234')\n        yield gen.Task(IOLoop.current().add_callback)\n        yield write(b'5678')\n\n    def test_sync_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_sync_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.sync_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_chunked(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer)\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_async_body_producer_content_length(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=self.async_body_producer,\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_chunked(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"])\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    @skipBefore35\n    def test_native_body_producer_content_length(self):\n        namespace = exec_test(globals(), locals(), \"\"\"\n        async def body_producer(write):\n            await write(b'1234')\n            await gen.Task(IOLoop.current().add_callback)\n            await write(b'5678')\n        \"\"\")\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body_producer=namespace[\"body_producer\"],\n                              headers={'Content-Length': '8'})\n        response.rethrow()\n        self.assertEqual(response.body, b\"12345678\")\n\n    def test_100_continue(self):\n        response = self.fetch(\"/echo_post\", method=\"POST\",\n                              body=b\"1234\",\n                              expect_100_continue=True)\n        self.assertEqual(response.body, b\"1234\")\n\n    def test_100_continue_early_response(self):\n        def body_producer(write):\n            raise Exception(\"should not be called\")\n        response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n                              body_producer=body_producer,\n                              expect_100_continue=True)\n        self.assertEqual(response.code, 403)\n\n    def test_streaming_follow_redirects(self):\n        # When following redirects, header and streaming callbacks\n        # should only be called for the final result.\n        # TODO(bdarnell): this test belongs in httpclient_test instead of\n        # simple_httpclient_test, but it fails with the version of libcurl\n        # available on travis-ci. Move it when that has been upgraded\n        # or we have a better framework to skip tests based on curl version.\n        headers = []\n        chunks = []\n        self.fetch(\"/redirect?url=/hello\",\n                   header_callback=headers.append,\n                   streaming_callback=chunks.append)\n        chunks = list(map(to_unicode, chunks))\n        self.assertEqual(chunks, ['Hello world!'])\n        # Make sure we only got one set of headers.\n        num_start_lines = len([h for h in headers if h.startswith(\"HTTP/\")])\n        self.assertEqual(num_start_lines, 1)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True, **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n    def test_ssl_options(self):\n        resp = self.fetch(\"/hello\", ssl_options={})\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_context(self):\n        resp = self.fetch(\"/hello\",\n                          ssl_options=ssl.SSLContext(ssl.PROTOCOL_SSLv23))\n        self.assertEqual(resp.body, b\"Hello world!\")\n\n    def test_ssl_options_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\",\n                       required=False):\n            resp = self.fetch(\n                \"/hello\", ssl_options=dict(cert_reqs=ssl.CERT_REQUIRED))\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_ssl_context_handshake_fail(self):\n        with ExpectLog(gen_log, \"SSL Error|Uncaught exception\"):\n            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n            ctx.verify_mode = ssl.CERT_REQUIRED\n            resp = self.fetch(\"/hello\", ssl_options=ctx)\n        self.assertRaises(ssl.SSLError, resp.rethrow)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors (in this case,\n        # failure to validate the testing self-signed cert).\n        # The SSLError is exposed through ssl.SSLError.\n        with ExpectLog(gen_log, '.*') as expect_log:\n            response = self.fetch(\"/\", validate_cert=True)\n            self.assertEqual(response.code, 599)\n            self.assertIsInstance(response.error, ssl.SSLError)\n        self.assertFalse(expect_log.logged_stack)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(res.body, b'A')\n\n\nclass HTTP204NoContentTestCase(AsyncHTTPTestCase):\n    def respond_204(self, request):\n        self.http1 = request.version.startswith('HTTP/1.')\n        if not self.http1:\n            # Close the request cleanly in HTTP/2; it will be skipped anyway.\n            request.connection.write_headers(ResponseStartLine('', 200, 'OK'),\n                                             HTTPHeaders())\n            request.connection.finish()\n            return\n\n        # A 204 response never has a body, even if doesn't have a content-length\n        # (which would otherwise mean read-until-close).  We simulate here a\n        # server that sends no content length and does not close the connection.\n        #\n        # Tests of a 204 response with no Content-Length header are included\n        # in SimpleHTTPClientTestMixin.\n        stream = request.connection.detach()\n        stream.write(b\"HTTP/1.1 204 No content\\r\\n\")\n        if request.arguments.get(\"error\", [False])[-1]:\n            stream.write(b\"Content-Length: 5\\r\\n\")\n        else:\n            stream.write(b\"Content-Length: 0\\r\\n\")\n        stream.write(b\"\\r\\n\")\n        stream.close()\n\n    def get_app(self):\n        return self.respond_204\n\n    def test_204_no_content(self):\n        resp = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(resp.code, 204)\n        self.assertEqual(resp.body, b'')\n\n    def test_204_invalid_content_length(self):\n        # 204 status with non-zero content length is malformed\n        with ExpectLog(gen_log, \".*Response with code 204 should not have body\"):\n            response = self.fetch(\"/?error=1\")\n            if not self.http1:\n                self.skipTest(\"requires HTTP/1.x\")\n            if self.http_client.configured_class != SimpleAsyncHTTPClient:\n                self.skipTest(\"curl client accepts invalid headers\")\n            self.assertEqual(response.code, 599)\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass ResolveTimeoutTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        # Dummy Resolver subclass that never invokes its callback.\n        class BadResolver(Resolver):\n            def resolve(self, *args, **kwargs):\n                pass\n\n        super(ResolveTimeoutTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            resolver=BadResolver())\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_resolve_timeout(self):\n        response = self.fetch('/hello', connect_timeout=0.1)\n        self.assertEqual(response.code, 599)\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 100)\n                self.write(\"ok\")\n\n        class LargeHeaders(RequestHandler):\n            def get(self):\n                self.set_header(\"X-Filler\", \"a\" * 1000)\n                self.write(\"ok\")\n\n        return Application([('/small', SmallHeaders),\n                            ('/large', LargeHeaders)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'ok')\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBodySizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class SmallBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 64)\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/small', SmallBody),\n                            ('/large', LargeBody)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 64)\n\n    def test_small_body(self):\n        response = self.fetch('/small')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 64)\n\n    def test_large_body(self):\n        with ExpectLog(gen_log, \"Malformed HTTP message from None: Content-Length too long\"):\n            response = self.fetch('/large')\n        self.assertEqual(response.code, 599)\n\n\nclass MaxBufferSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class LargeBody(RequestHandler):\n            def get(self):\n                self.write(\"a\" * 1024 * 100)\n\n        return Application([('/large', LargeBody)])\n\n    def get_http_client(self):\n        # 100KB body with 64KB buffer\n        return SimpleAsyncHTTPClient(max_body_size=1024 * 100, max_buffer_size=1024 * 64)\n\n    def test_large_body(self):\n        response = self.fetch('/large')\n        response.rethrow()\n        self.assertEqual(response.body, b'a' * 1024 * 100)\n\n\nclass ChunkedWithContentLengthTest(AsyncHTTPTestCase):\n    def get_app(self):\n\n        class ChunkedWithContentLength(RequestHandler):\n            def get(self):\n                # Add an invalid Transfer-Encoding to the response\n                self.set_header('Transfer-Encoding', 'chunked')\n                self.write(\"Hello world\")\n\n        return Application([('/chunkwithcl', ChunkedWithContentLength)])\n\n    def get_http_client(self):\n        return SimpleAsyncHTTPClient()\n\n    def test_chunked_with_content_length(self):\n        # Make sure the invalid headers are detected\n        with ExpectLog(gen_log, (\"Malformed HTTP message from None: Response \"\n                                 \"with both Transfer-Encoding and Content-Length\")):\n            response = self.fetch('/chunkwithcl')\n        self.assertEqual(response.code, 599)\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n    def tearDown(self):\n        # Reset signal handlers\n        from twisted.internet import reactor\n\n        reactor.removeAll()\n        reactor.stop()\n        super().tearDown()\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\".\", pattern=\"test_*.py\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "test_2.py",
        "tornado_unittest_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 815ms\nPrepared 1 package in 1.08s\nInstalled 1 package in 25ms\n + tornado==5.0.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e)\nResolved 29 packages in 12ms\nInstalled 29 packages in 153ms\n + attrs==24.3.0\n + automat==24.8.1\n + cachetools==5.5.0\n + cffi==1.17.1\n + chardet==5.2.0\n + colorama==0.4.6\n + constantly==23.10.4\n + distlib==0.3.9\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + hyperlink==21.0.0\n + idna==3.10\n + incremental==24.7.2\n + iniconfig==2.0.0\n + packaging==24.2\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pycares==4.5.0\n + pycparser==2.22\n + pycurl==7.45.4\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + setuptools==75.6.0\n + tomli==2.2.1\n + tox==4.23.2\n + twisted==24.11.0\n + typing-extensions==4.12.2\n + virtualenv==20.28.0\n + zope-interface==7.2\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e\n........................................................................................................................................................................................................................................................................................\ncollected 280 items\n\n=================================== FAILURES ===================================\n__________ GzipTestCase.test_gzip_static __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1590, in test_gzip_static\n    self.assert_compressed(response)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1575, in assert_compressed\n    self.assertEqual(\nAssertionError: None != 'gzip'\n__________ StaticDefaultFilenameTest.test_static_default_filename __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1244, in test_static_default_filename\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticDefaultFilenameTest.test_static_default_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1249, in test_static_default_redirect\n    self.assertEqual(response.code, 301)\nAssertionError: 404 != 301\n__________ StaticFileTest.test_absolute_static_url __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1013, in test_absolute_static_url\n    self.assertEqual(response.body, (\nAssertionError: b'http://127.0.0.1:43561/static/robots.txt' != b'http://127.0.0.1:43561/static/robots.txt?v=f71d20196d4caf35b6a670db8c70b03d'\n__________ StaticFileTest.test_root_static_path __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1230, in test_root_static_path\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_compressed_files __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 996, in test_static_compressed_files\n    self.assertEqual(response.headers.get(\"Content-Type\"),\nAssertionError: 'text/html; charset=UTF-8' != 'application/gzip'\n- text/html; charset=UTF-8\n+ application/gzip\n\n__________ StaticFileTest.test_static_etag __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1095, in test_static_etag\n    self.assertEqual(utf8(response.headers.get(\"Etag\")),\nAssertionError: None != b'\"f71d20196d4caf35b6a670db8c70b03d\"'\n__________ StaticFileTest.test_static_files __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 988, in test_static_files\n    self.assertTrue(b\"Disallow: /\" in response.body)\nAssertionError: False is not true\n__________ StaticFileTest.test_static_head __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1178, in test_static_head\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_head_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1188, in test_static_head_range\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileTest.test_static_if_modified_since_pre_epoch __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1077, in test_static_if_modified_since_pre_epoch\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_invalid_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1160, in test_static_invalid_range\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_range_if_none_match __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1198, in test_static_range_if_none_match\n    self.assertEqual(response.code, 304)\nAssertionError: 404 != 304\n__________ StaticFileTest.test_static_unsatisfiable_range_invalid_start __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1172, in test_static_unsatisfiable_range_invalid_start\n    self.assertEqual(response.code, 416)\nAssertionError: 404 != 416\n__________ StaticFileTest.test_static_unsatisfiable_range_zero_suffix __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1165, in test_static_unsatisfiable_range_zero_suffix\n    self.assertEqual(response.headers.get(\"Content-Range\"),\nAssertionError: None != 'bytes */26'\n__________ StaticFileTest.test_static_url __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1008, in test_static_url\n    self.assertEqual(response.body,\nAssertionError: b'/static/robots.txt' != b'/static/robots.txt?v=f71d20196d4caf35b6a670db8c70b03d'\n__________ StaticFileTest.test_static_with_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1101, in test_static_with_range\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileTest.test_static_with_range_end_edge __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1144, in test_static_with_range_end_edge\n    self.assertEqual(response.body, b\": /\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b': /\\n'\n__________ StaticFileTest.test_static_with_range_full_file __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1114, in test_static_with_range_full_file\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_with_range_full_past_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1124, in test_static_with_range_full_past_end\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_with_range_neg_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1152, in test_static_with_range_neg_end\n    self.assertEqual(response.body, b\": /\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b': /\\n'\n__________ StaticFileTest.test_static_with_range_partial_past_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1134, in test_static_with_range_partial_past_end\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileWithPathTest.test_serve __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1266, in test_serve\n    self.assertEqual(response.body, b\"H\\xc3\\xa9llo\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b'H\\xc3\\xa9llo\\n'\n\n=================================== ERRORS =====================================\n__________ StaticFileTest.test_static_304_if_modified_since __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1060, in test_static_304_if_modified_since\n    'If-Modified-Since': response1.headers['Last-Modified']})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/httputil.py\", line 217, in __getitem__\n    return self._dict[_normalized_headers[name]]\nKeyError: 'Last-Modified'\n__________ StaticFileTest.test_static_304_if_none_match __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1068, in test_static_304_if_none_match\n    'If-None-Match': response1.headers['Etag']})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/httputil.py\", line 217, in __getitem__\n    return self._dict[_normalized_headers[name]]\nKeyError: 'Etag'\n__________ StaticFileTest.test_static_if_modified_since_time_zone __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1084, in test_static_if_modified_since_time_zone\n    stat = os.stat(relpath('static/robots.txt'))\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt'\n__________ ChunkedWithContentLengthTest.test_chunked_with_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 766, in test_chunked_with_content_length\n    response = self.fetch('/chunkwithcl')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ MaxBodySizeTest.test_large_body __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 725, in test_large_body\n    response = self.fetch('/large')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ MaxHeaderSizeTest.test_large_headers __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 698, in test_large_headers\n    response = self.fetch('/large')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ SimpleHTTPSClientTestCase.test_100_continue __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 438, in test_100_continue\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_100_continue_early_response __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 446, in test_100_continue_early_response\n    response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_async_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 398, in test_async_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_async_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 404, in test_async_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 172, in test_connection_limit\n    self.wait(condition=lambda: len(self.triggers) == 2)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_error_logging __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 517, in test_error_logging\n    response = self.fetch(\"/\", validate_cert=True)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_gzip __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 203, in test_gzip\n    response = self.fetch(\"/chunk\", use_gzip=False,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_head_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 300, in test_head_request\n    response = self.fetch(\"/head\", method=\"HEAD\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_header_reuse __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 226, in test_header_reuse\n    self.fetch(\"/hello\", headers=headers)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_host_header __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 323, in test_host_header\n    response = self.fetch(\"/host_echo\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ipv6 __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 285, in test_ipv6\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_max_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 214, in test_max_redirects\n    response = self.fetch(\"/countdown/5\", max_redirects=3)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_native_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 418, in test_native_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_native_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 431, in test_native_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 313, in test_no_content\n    response = self.fetch(\"/no_content\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 368, in test_no_content_length\n    response = self.fetch(\"/no_content_length\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_options_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 306, in test_options_request\n    response = self.fetch(\"/options\", method=\"OPTIONS\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_queue_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 356, in test_queue_timeout\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_redirect_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 195, in test_redirect_connection_limit\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_request_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 264, in test_request_timeout\n    response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_see_other_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 231, in test_see_other_redirect\n    response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_context __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 494, in test_ssl_context\n    resp = self.fetch(\"/hello\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_context_handshake_fail __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 509, in test_ssl_context_handshake_fail\n    resp = self.fetch(\"/hello\", ssl_options=ctx)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_options __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 490, in test_ssl_options\n    resp = self.fetch(\"/hello\", ssl_options={})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_options_handshake_fail __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 501, in test_ssl_options_handshake_fail\n    resp = self.fetch(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_streaming_follow_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 460, in test_streaming_follow_redirects\n    self.fetch(\"/redirect?url=/hello\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_sync_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 385, in test_sync_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_sync_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 391, in test_sync_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::AllHTTPMethodsTest::test_standard_methods\nPASSED r2e_tests.test_1::ApplicationTest::test_listen\nPASSED r2e_tests.test_1::AuthRedirectTest::test_absolute_auth_redirect\nPASSED r2e_tests.test_1::AuthRedirectTest::test_relative_auth_redirect\nPASSED r2e_tests.test_1::BuggyLoggingTest::test_buggy_log_exception\nPASSED r2e_tests.test_1::CacheTest::test_multiple_strong_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_strong_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_weak_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_weak_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_strong_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_strong_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_weak_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_weak_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_wildcard_etag\nPASSED r2e_tests.test_1::ClearAllCookiesTest::test_clear_all_cookies\nPASSED r2e_tests.test_1::ClearHeaderTest::test_clear_header\nPASSED r2e_tests.test_1::ClientCloseTest::test_client_close\nPASSED r2e_tests.test_1::ConnectionCloseTest::test_connection_close\nPASSED r2e_tests.test_1::CookieTest::test_cookie_special_char\nPASSED r2e_tests.test_1::CookieTest::test_get_cookie\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_domain\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_expires_days\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_false_flags\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_max_age\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_overwrite\nPASSED r2e_tests.test_1::Custom404Test::test_404\nPASSED r2e_tests.test_1::CustomStaticFileTest::test_serve\nPASSED r2e_tests.test_1::CustomStaticFileTest::test_static_url\nPASSED r2e_tests.test_1::DateHeaderTest::test_date_header\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_chunked_body\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_compressed_body\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_fixed_body\nPASSED r2e_tests.test_1::DecoratorTest::test_addslash\nPASSED r2e_tests.test_1::DecoratorTest::test_removeslash\nPASSED r2e_tests.test_1::Default404Test::test_404\nPASSED r2e_tests.test_1::DefaultHandlerArgumentsTest::test_403\nPASSED r2e_tests.test_1::DefaultHostMatchingTest::test_default_host_matching\nPASSED r2e_tests.test_1::ErrorHandlerXSRFTest::test_404_xsrf\nPASSED r2e_tests.test_1::ErrorHandlerXSRFTest::test_error_xsrf\nPASSED r2e_tests.test_1::ErrorResponseTest::test_default\nPASSED r2e_tests.test_1::ErrorResponseTest::test_failed_write_error\nPASSED r2e_tests.test_1::ErrorResponseTest::test_write_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_http_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_known_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_unknown_error\nPASSED r2e_tests.test_1::FinishExceptionTest::test_finish_exception\nPASSED r2e_tests.test_1::FinishInPrepareTest::test_finish_in_prepare\nPASSED r2e_tests.test_1::GetArgumentErrorTest::test_catch_error\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_from_ui_module_is_lazy\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_from_ui_module_works\nSKIPPED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_is_lazy\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_works\nPASSED r2e_tests.test_1::GzipTestCase::test_gzip\nPASSED r2e_tests.test_1::GzipTestCase::test_gzip_not_requested\nFAILED r2e_tests.test_1::GzipTestCase::test_gzip_static\nPASSED r2e_tests.test_1::GzipTestCase::test_vary_already_present\nPASSED r2e_tests.test_1::GzipTestCase::test_vary_already_present_multiple\nPASSED r2e_tests.test_1::HTTPErrorTest::test_copy\nPASSED r2e_tests.test_1::HandlerByNameTest::test_handler_by_name\nPASSED r2e_tests.test_1::Header204Test::test_204_headers\nPASSED r2e_tests.test_1::Header304Test::test_304_headers\nPASSED r2e_tests.test_1::HostMatchingTest::test_host_matching\nPASSED r2e_tests.test_1::IncorrectContentLengthTest::test_content_length_too_high\nPASSED r2e_tests.test_1::IncorrectContentLengthTest::test_content_length_too_low\nPASSED r2e_tests.test_1::MultipleExceptionTest::test_multi_exception\nPASSED r2e_tests.test_1::NamedURLSpecGroupsTest::test_named_urlspec_groups\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_chunked_body\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_compressed_body\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_fixed_body\nPASSED r2e_tests.test_1::NonWSGIWebTests::test_empty_flush\nPASSED r2e_tests.test_1::NonWSGIWebTests::test_flow_control\nPASSED r2e_tests.test_1::PatchMethodTest::test_other\nPASSED r2e_tests.test_1::PatchMethodTest::test_patch\nPASSED r2e_tests.test_1::PathArgsInPrepareTest::test_kw\nPASSED r2e_tests.test_1::PathArgsInPrepareTest::test_pos\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_httperror_str\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_httperror_str_from_httputil\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_raise_with_reason\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_basic_redirect\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_pattern\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_with_appending_argument\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_with_argument\nPASSED r2e_tests.test_1::RequestEncodingTest::test_error\nPASSED r2e_tests.test_1::RequestEncodingTest::test_group_encoding\nPASSED r2e_tests.test_1::RequestEncodingTest::test_group_question_mark\nPASSED r2e_tests.test_1::RequestEncodingTest::test_slashes\nPASSED r2e_tests.test_1::RequestSummaryTest::test_missing_remote_ip\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_arbitrary_bytes\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_cookie_tampering_future_timestamp\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_round_trip\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_increment_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_invalidate_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_roundtrip\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_roundtrip_differing_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_round_trip\nPASSED r2e_tests.test_1::SetLazyPropertiesTest::test_set_properties\nPASSED r2e_tests.test_1::SignedValueTest::test_expired\nPASSED r2e_tests.test_1::SignedValueTest::test_key_version_retrieval\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_invalid_key\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_read_write_default_key\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_read_write_non_default_key\nPASSED r2e_tests.test_1::SignedValueTest::test_known_values\nPASSED r2e_tests.test_1::SignedValueTest::test_name_swap\nPASSED r2e_tests.test_1::SignedValueTest::test_non_ascii\nPASSED r2e_tests.test_1::SignedValueTest::test_payload_tampering\nPASSED r2e_tests.test_1::SignedValueTest::test_signature_tampering\nFAILED r2e_tests.test_1::StaticDefaultFilenameTest::test_static_default_filename\nFAILED r2e_tests.test_1::StaticDefaultFilenameTest::test_static_default_redirect\nFAILED r2e_tests.test_1::StaticFileTest::test_absolute_static_url\nPASSED r2e_tests.test_1::StaticFileTest::test_absolute_version_exclusion\nPASSED r2e_tests.test_1::StaticFileTest::test_include_host_override\nPASSED r2e_tests.test_1::StaticFileTest::test_path_traversal_protection\nPASSED r2e_tests.test_1::StaticFileTest::test_relative_version_exclusion\nFAILED r2e_tests.test_1::StaticFileTest::test_root_static_path\nERROR r2e_tests.test_1::StaticFileTest::test_static_304_if_modified_since\nERROR r2e_tests.test_1::StaticFileTest::test_static_304_if_none_match\nPASSED r2e_tests.test_1::StaticFileTest::test_static_404\nFAILED r2e_tests.test_1::StaticFileTest::test_static_compressed_files\nFAILED r2e_tests.test_1::StaticFileTest::test_static_etag\nFAILED r2e_tests.test_1::StaticFileTest::test_static_files\nFAILED r2e_tests.test_1::StaticFileTest::test_static_head\nFAILED r2e_tests.test_1::StaticFileTest::test_static_head_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_if_modified_since_pre_epoch\nERROR r2e_tests.test_1::StaticFileTest::test_static_if_modified_since_time_zone\nFAILED r2e_tests.test_1::StaticFileTest::test_static_invalid_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_range_if_none_match\nFAILED r2e_tests.test_1::StaticFileTest::test_static_unsatisfiable_range_invalid_start\nFAILED r2e_tests.test_1::StaticFileTest::test_static_unsatisfiable_range_zero_suffix\nFAILED r2e_tests.test_1::StaticFileTest::test_static_url\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_end_edge\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_full_file\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_full_past_end\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_neg_end\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_partial_past_end\nFAILED r2e_tests.test_1::StaticFileWithPathTest::test_serve\nPASSED r2e_tests.test_1::StatusReasonTest::test_status\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_close_during_upload\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_early_return\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_early_return_with_data\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_streaming_body\nPASSED r2e_tests.test_1::UIMethodUIModuleTest::test_ui_method\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_non_reversible\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_reverse\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_reverse_arguments\nPASSED r2e_tests.test_1::UnimplementedHTTPMethodsTest::test_unimplemented_standard_methods\nPASSED r2e_tests.test_1::UnimplementedNonStandardMethodsTest::test_unimplemented_other\nPASSED r2e_tests.test_1::UnimplementedNonStandardMethodsTest::test_unimplemented_patch\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument_invalid_unicode\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument_plus\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_argument\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_body_arguments\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_query_arguments\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_header_injection\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_multi_header\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_no_gzip\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_optional_path\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_redirect\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_reverse_url\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_types\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_uimodule_resources\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_uimodule_unescaped\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_web_redirect\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_web_redirect_double_slash\nPASSED r2e_tests.test_1::XSRFCookieKwargsTest::test_xsrf_httponly\nPASSED r2e_tests.test_1::XSRFTest::test_cross_user\nPASSED r2e_tests.test_1::XSRFTest::test_distinct_tokens\nPASSED r2e_tests.test_1::XSRFTest::test_refresh_token\nPASSED r2e_tests.test_1::XSRFTest::test_versioning\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_argument_invalid_format\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_body_no_cookie\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_cookie_invalid_format\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_cookie_no_body\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_no_token\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_header\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_non_hex_token\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_post_body\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_query_string\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_short_token\nERROR r2e_tests.test_2::ChunkedWithContentLengthTest::test_chunked_with_content_length\nPASSED r2e_tests.test_2::CreateAsyncHTTPClientTestCase::test_max_clients\nPASSED r2e_tests.test_2::HTTP100ContinueTestCase::test_100_continue\nSKIPPED r2e_tests.test_2::HTTP204NoContentTestCase::test_204_invalid_content_length\nPASSED r2e_tests.test_2::HTTP204NoContentTestCase::test_204_no_content\nPASSED r2e_tests.test_2::HostnameMappingTestCase::test_hostname_mapping\nPASSED r2e_tests.test_2::HostnameMappingTestCase::test_port_mapping\nERROR r2e_tests.test_2::MaxBodySizeTest::test_large_body\nPASSED r2e_tests.test_2::MaxBodySizeTest::test_small_body\nPASSED r2e_tests.test_2::MaxBufferSizeTest::test_large_body\nERROR r2e_tests.test_2::MaxHeaderSizeTest::test_large_headers\nPASSED r2e_tests.test_2::MaxHeaderSizeTest::test_small_headers\nPASSED r2e_tests.test_2::ResolveTimeoutTestCase::test_resolve_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_304_with_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_all_methods\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_basic_auth\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_basic_auth_explicit_mode\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_body_encoding\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_body_sanity_checks\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_chunked_close\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_configure_defaults\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_credentials_in_url\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_final_callback_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_follow_redirect\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_http_error\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_http_error_no_raise\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_interface\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_callback\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_callback_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_types\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_hello_world\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_multi_line_headers\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_non_ascii_header\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_patch_receives_payload\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_post\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_put_307\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_reuse_request_from_response\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_streaming_callback\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_streaming_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_types\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_unsupported_auth_mode\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_100_continue\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_100_continue_early_response\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_async_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_async_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connect_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_header_reuse\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_native_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_native_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_no_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_queue_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_singleton\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_streaming_follow_redirects\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_sync_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_sync_body_producer_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_100_continue\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_100_continue_early_response\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_async_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_async_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connect_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connection_refused\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_error_logging\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_gzip\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_head_request\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_header_reuse\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_host_header\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ipv6\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_max_redirects\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_native_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_native_body_producer_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_no_content\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_no_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_options_request\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_queue_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_redirect_connection_limit\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_request_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_singleton\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_context\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_context_handshake_fail\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_options\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_options_handshake_fail\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_streaming_follow_redirects\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_sync_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_sync_body_producer_content_length\n=================== 23 failed, 34 errors, 221 passed, 2 skipped in 1.78s ===================\n",
    "new_commit_res_stderr": "WARNING:tornado.access:405 HEAD / (127.0.0.1) 0.26ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.29ms\nWARNING:tornado.access:404 GET / (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 GET / (127.0.0.1) 0.20ms\nWARNING:tornado.access:403 GET / (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 GET /baz (127.0.0.1) 0.20ms\nWARNING:tornado.access:404 GET /foo (127.0.0.1) 0.18ms\nWARNING:tornado.access:404 POST /404 (127.0.0.1) 0.23ms\nWARNING:tornado.access:417 POST /error (127.0.0.1) 0.23ms\nERROR:tornado.access:500 GET /default (127.0.0.1) 0.26ms\nERROR:tornado.access:503 GET /default?status=503 (127.0.0.1) 0.21ms\nWARNING:tornado.access:435 GET /default?status=435 (127.0.0.1) 0.21ms\nERROR:tornado.access:500 GET /failed_write_error (127.0.0.1) 0.26ms\nERROR:tornado.access:500 GET /write_error (127.0.0.1) 0.24ms\nERROR:tornado.access:503 GET /write_error?status=503 (127.0.0.1) 0.19ms\nWARNING:tornado.access:410 GET /?exc=http (127.0.0.1) 0.26ms\nWARNING:tornado.access:403 GET /?exc=permission (127.0.0.1) 0.28ms\nERROR:tornado.access:500 GET /?exc=zero (127.0.0.1) 0.25ms\nWARNING:tornado.access:401 GET / (127.0.0.1) 0.19ms\nWARNING:tornado.access:401 GET /?finish_value=1 (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 GET /robots.txt (127.0.0.1) 0.31ms\nWARNING:tornado.access:404 GET /bar (127.0.0.1) 0.29ms\nWARNING:tornado.access:404 GET /baz (127.0.0.1) 0.28ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.30ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.24ms\nERROR:tornado.access:682 GET / (127.0.0.1) 0.28ms\nWARNING:tornado.access:400 GET /group/?arg=%25%e9 (127.0.0.1) 0.45ms\nWARNING:tornado.access:404 GET /static/dir/ (127.0.0.1) 0.31ms\nWARNING:tornado.access:404 GET /static/dir (127.0.0.1) 0.28ms\nERROR:tornado.general:Could not open static file '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt'\nWARNING:tornado.access:403 HEAD /static/../static_foo.txt (127.0.0.1) 0.32ms\nWARNING:tornado.access:403 GET /static/../static_foo.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 HEAD /root_static/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt (127.0.0.1) 0.29ms\nWARNING:tornado.access:404 GET /root_static/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/blarg (127.0.0.1) 0.27ms\nWARNING:tornado.access:404 GET /static/blarg (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/sample.xml.gz (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.27ms\nWARNING:tornado.access:404 GET /robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.27ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.43ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 GET /foo/utf8.html (127.0.0.1) 0.25ms\nERROR:tornado.access:682 GET /?code=682&reason=Bar (127.0.0.1) 0.18ms\nERROR:tornado.access:682 GET /?code=682 (127.0.0.1) 0.18ms\nWARNING:tornado.access:401 GET /early_return (127.0.0.1) 0.18ms\nWARNING:tornado.access:401 GET /early_return (127.0.0.1) 0.17ms\nWARNING:tornado.access:405 HEAD / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 GET / (127.0.0.1) 0.19ms\nWARNING:tornado.access:405 DELETE / (127.0.0.1) 0.18ms\nWARNING:tornado.access:405 OPTIONS / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 POST / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 PUT / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 OTHER / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 PATCH / (127.0.0.1) 0.38ms\nWARNING:tornado.access:400 GET /typecheck/invalid%FF (127.0.0.1) 0.27ms\nWARNING:tornado.access:400 GET /typecheck/invalid?foo=%FF (127.0.0.1) 0.27ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.33ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.30ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.34ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.31ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.33ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.33ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.29ms\nWARNING:tornado.access:405 HEAD /all_methods (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.32ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.21ms\nWARNING:tornado.access:403 POST /respond_in_prepare (127.0.0.1) 0.18ms\nERROR:tornado.application:Future <tornado.concurrent.Future object at 0x7b6aa5e33790> exception was never retrieved: Traceback (most recent call last):\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/gen.py\", line 303, in wrapper\n    yielded = next(result)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpclient.py\", line 225, in connect\n    addrinfo = yield self.resolver.resolve(host, port, af)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/concurrent.py\", line 401, in wrapper\n    future = getattr(self, executor).submit(fn, self, *args, **kwargs)\nAttributeError: 'NoneType' object has no attribute 'submit'\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e\n........................................................................................................................................................................................................................................................................................\ncollected 280 items\n\n=================================== FAILURES ===================================\n__________ AuthRedirectTest.test_absolute_auth_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 358, in test_absolute_auth_redirect\n    self.assertTrue(re.match(\nAssertionError: None is not true : http://example.com/login?next=http%3A%2F%2Flocalhost%3A33377%2Fabsolute\n__________ GzipTestCase.test_gzip_static __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1590, in test_gzip_static\n    self.assert_compressed(response)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1575, in assert_compressed\n    self.assertEqual(\nAssertionError: None != 'gzip'\n__________ StaticDefaultFilenameTest.test_static_default_filename __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1244, in test_static_default_filename\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticDefaultFilenameTest.test_static_default_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1249, in test_static_default_redirect\n    self.assertEqual(response.code, 301)\nAssertionError: 404 != 301\n__________ StaticFileTest.test_absolute_static_url __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1013, in test_absolute_static_url\n    self.assertEqual(response.body, (\nAssertionError: b'http://localhost:44541/static/robots.txt' != b'http://localhost:44541/static/robots.txt?v=f71d20196d4caf35b6a670db8c70b03d'\n__________ StaticFileTest.test_root_static_path __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1230, in test_root_static_path\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_compressed_files __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 996, in test_static_compressed_files\n    self.assertEqual(response.headers.get(\"Content-Type\"),\nAssertionError: 'text/html; charset=UTF-8' != 'application/gzip'\n- text/html; charset=UTF-8\n+ application/gzip\n\n__________ StaticFileTest.test_static_etag __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1095, in test_static_etag\n    self.assertEqual(utf8(response.headers.get(\"Etag\")),\nAssertionError: None != b'\"f71d20196d4caf35b6a670db8c70b03d\"'\n__________ StaticFileTest.test_static_files __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 988, in test_static_files\n    self.assertTrue(b\"Disallow: /\" in response.body)\nAssertionError: False is not true\n__________ StaticFileTest.test_static_head __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1178, in test_static_head\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_head_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1188, in test_static_head_range\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileTest.test_static_if_modified_since_pre_epoch __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1077, in test_static_if_modified_since_pre_epoch\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_invalid_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1160, in test_static_invalid_range\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_range_if_none_match __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1198, in test_static_range_if_none_match\n    self.assertEqual(response.code, 304)\nAssertionError: 404 != 304\n__________ StaticFileTest.test_static_unsatisfiable_range_invalid_start __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1172, in test_static_unsatisfiable_range_invalid_start\n    self.assertEqual(response.code, 416)\nAssertionError: 404 != 416\n__________ StaticFileTest.test_static_unsatisfiable_range_zero_suffix __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1165, in test_static_unsatisfiable_range_zero_suffix\n    self.assertEqual(response.headers.get(\"Content-Range\"),\nAssertionError: None != 'bytes */26'\n__________ StaticFileTest.test_static_url __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1008, in test_static_url\n    self.assertEqual(response.body,\nAssertionError: b'/static/robots.txt' != b'/static/robots.txt?v=f71d20196d4caf35b6a670db8c70b03d'\n__________ StaticFileTest.test_static_with_range __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1101, in test_static_with_range\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileTest.test_static_with_range_end_edge __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1144, in test_static_with_range_end_edge\n    self.assertEqual(response.body, b\": /\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b': /\\n'\n__________ StaticFileTest.test_static_with_range_full_file __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1114, in test_static_with_range_full_file\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_with_range_full_past_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1124, in test_static_with_range_full_past_end\n    self.assertEqual(response.code, 200)\nAssertionError: 404 != 200\n__________ StaticFileTest.test_static_with_range_neg_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1152, in test_static_with_range_neg_end\n    self.assertEqual(response.body, b\": /\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b': /\\n'\n__________ StaticFileTest.test_static_with_range_partial_past_end __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1134, in test_static_with_range_partial_past_end\n    self.assertEqual(response.code, 206)\nAssertionError: 404 != 206\n__________ StaticFileWithPathTest.test_serve __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1266, in test_serve\n    self.assertEqual(response.body, b\"H\\xc3\\xa9llo\\n\")\nAssertionError: b'<html><title>404: Not Found</title><body>404: Not Found</body></html>' != b'H\\xc3\\xa9llo\\n'\n__________ SimpleHTTPClientTestCase.test_host_header __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 324, in test_host_header\n    self.assertTrue(host_re.match(response.body))\nAssertionError: None is not true\n\n=================================== ERRORS =====================================\n__________ StaticFileTest.test_static_304_if_modified_since __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1060, in test_static_304_if_modified_since\n    'If-Modified-Since': response1.headers['Last-Modified']})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/httputil.py\", line 217, in __getitem__\n    return self._dict[_normalized_headers[name]]\nKeyError: 'Last-Modified'\n__________ StaticFileTest.test_static_304_if_none_match __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1068, in test_static_304_if_none_match\n    'If-None-Match': response1.headers['Etag']})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/httputil.py\", line 217, in __getitem__\n    return self._dict[_normalized_headers[name]]\nKeyError: 'Etag'\n__________ StaticFileTest.test_static_if_modified_since_time_zone __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_1.py\", line 1084, in test_static_if_modified_since_time_zone\n    stat = os.stat(relpath('static/robots.txt'))\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt'\n__________ ChunkedWithContentLengthTest.test_chunked_with_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 766, in test_chunked_with_content_length\n    response = self.fetch('/chunkwithcl')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ MaxBodySizeTest.test_large_body __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 725, in test_large_body\n    response = self.fetch('/large')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ MaxHeaderSizeTest.test_large_headers __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 698, in test_large_headers\n    response = self.fetch('/large')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 595, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ SimpleHTTPSClientTestCase.test_100_continue __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 438, in test_100_continue\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_100_continue_early_response __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 446, in test_100_continue_early_response\n    response = self.fetch(\"/respond_in_prepare\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_async_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 398, in test_async_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_async_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 404, in test_async_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 172, in test_connection_limit\n    self.wait(condition=lambda: len(self.triggers) == 2)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_error_logging __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 517, in test_error_logging\n    response = self.fetch(\"/\", validate_cert=True)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_gzip __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 203, in test_gzip\n    response = self.fetch(\"/chunk\", use_gzip=False,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_head_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 300, in test_head_request\n    response = self.fetch(\"/head\", method=\"HEAD\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_header_reuse __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 226, in test_header_reuse\n    self.fetch(\"/hello\", headers=headers)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_host_header __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 323, in test_host_header\n    response = self.fetch(\"/host_echo\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ipv6 __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 285, in test_ipv6\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_max_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 214, in test_max_redirects\n    response = self.fetch(\"/countdown/5\", max_redirects=3)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_native_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 418, in test_native_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_native_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 431, in test_native_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 313, in test_no_content\n    response = self.fetch(\"/no_content\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 368, in test_no_content_length\n    response = self.fetch(\"/no_content_length\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_options_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 306, in test_options_request\n    response = self.fetch(\"/options\", method=\"OPTIONS\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_queue_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 356, in test_queue_timeout\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_redirect_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 195, in test_redirect_connection_limit\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_request_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 264, in test_request_timeout\n    response = self.fetch('/trigger?wake=false', request_timeout=timeout)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_see_other_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 231, in test_see_other_redirect\n    response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_context __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 494, in test_ssl_context\n    resp = self.fetch(\"/hello\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_context_handshake_fail __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 509, in test_ssl_context_handshake_fail\n    resp = self.fetch(\"/hello\", ssl_options=ctx)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_options __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 490, in test_ssl_options\n    resp = self.fetch(\"/hello\", ssl_options={})\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ssl_options_handshake_fail __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 501, in test_ssl_options_handshake_fail\n    resp = self.fetch(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_streaming_follow_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 460, in test_streaming_follow_redirects\n    self.fetch(\"/redirect?url=/hello\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_sync_body_producer_chunked __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 385, in test_sync_body_producer_chunked\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_sync_body_producer_content_length __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/test_2.py\", line 391, in test_sync_body_producer_content_length\n    response = self.fetch(\"/echo_post\", method=\"POST\",\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 390, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 315, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/testing.py\", line 251, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 4, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/stack_context.py\", line 316, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 252, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpserver.py\", line 263, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 502, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/netutil.py\", line 477, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::AllHTTPMethodsTest::test_standard_methods\nPASSED r2e_tests.test_1::ApplicationTest::test_listen\nFAILED r2e_tests.test_1::AuthRedirectTest::test_absolute_auth_redirect\nPASSED r2e_tests.test_1::AuthRedirectTest::test_relative_auth_redirect\nPASSED r2e_tests.test_1::BuggyLoggingTest::test_buggy_log_exception\nPASSED r2e_tests.test_1::CacheTest::test_multiple_strong_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_strong_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_weak_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_multiple_weak_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_strong_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_strong_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_weak_etag_match\nPASSED r2e_tests.test_1::CacheTest::test_weak_etag_not_match\nPASSED r2e_tests.test_1::CacheTest::test_wildcard_etag\nPASSED r2e_tests.test_1::ClearAllCookiesTest::test_clear_all_cookies\nPASSED r2e_tests.test_1::ClearHeaderTest::test_clear_header\nPASSED r2e_tests.test_1::ClientCloseTest::test_client_close\nPASSED r2e_tests.test_1::ConnectionCloseTest::test_connection_close\nPASSED r2e_tests.test_1::CookieTest::test_cookie_special_char\nPASSED r2e_tests.test_1::CookieTest::test_get_cookie\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_domain\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_expires_days\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_false_flags\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_max_age\nPASSED r2e_tests.test_1::CookieTest::test_set_cookie_overwrite\nPASSED r2e_tests.test_1::Custom404Test::test_404\nPASSED r2e_tests.test_1::CustomStaticFileTest::test_serve\nPASSED r2e_tests.test_1::CustomStaticFileTest::test_static_url\nPASSED r2e_tests.test_1::DateHeaderTest::test_date_header\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_chunked_body\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_compressed_body\nPASSED r2e_tests.test_1::DecoratedStreamingRequestFlowControlTest::test_flow_control_fixed_body\nPASSED r2e_tests.test_1::DecoratorTest::test_addslash\nPASSED r2e_tests.test_1::DecoratorTest::test_removeslash\nPASSED r2e_tests.test_1::Default404Test::test_404\nPASSED r2e_tests.test_1::DefaultHandlerArgumentsTest::test_403\nPASSED r2e_tests.test_1::DefaultHostMatchingTest::test_default_host_matching\nPASSED r2e_tests.test_1::ErrorHandlerXSRFTest::test_404_xsrf\nPASSED r2e_tests.test_1::ErrorHandlerXSRFTest::test_error_xsrf\nPASSED r2e_tests.test_1::ErrorResponseTest::test_default\nPASSED r2e_tests.test_1::ErrorResponseTest::test_failed_write_error\nPASSED r2e_tests.test_1::ErrorResponseTest::test_write_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_http_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_known_error\nPASSED r2e_tests.test_1::ExceptionHandlerTest::test_unknown_error\nPASSED r2e_tests.test_1::FinishExceptionTest::test_finish_exception\nPASSED r2e_tests.test_1::FinishInPrepareTest::test_finish_in_prepare\nPASSED r2e_tests.test_1::GetArgumentErrorTest::test_catch_error\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_from_ui_module_is_lazy\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_from_ui_module_works\nSKIPPED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_is_lazy\nPASSED r2e_tests.test_1::GetCurrentUserTest::test_get_current_user_works\nPASSED r2e_tests.test_1::GzipTestCase::test_gzip\nPASSED r2e_tests.test_1::GzipTestCase::test_gzip_not_requested\nFAILED r2e_tests.test_1::GzipTestCase::test_gzip_static\nPASSED r2e_tests.test_1::GzipTestCase::test_vary_already_present\nPASSED r2e_tests.test_1::GzipTestCase::test_vary_already_present_multiple\nPASSED r2e_tests.test_1::HTTPErrorTest::test_copy\nPASSED r2e_tests.test_1::HandlerByNameTest::test_handler_by_name\nPASSED r2e_tests.test_1::Header204Test::test_204_headers\nPASSED r2e_tests.test_1::Header304Test::test_304_headers\nPASSED r2e_tests.test_1::HostMatchingTest::test_host_matching\nPASSED r2e_tests.test_1::IncorrectContentLengthTest::test_content_length_too_high\nPASSED r2e_tests.test_1::IncorrectContentLengthTest::test_content_length_too_low\nPASSED r2e_tests.test_1::MultipleExceptionTest::test_multi_exception\nPASSED r2e_tests.test_1::NamedURLSpecGroupsTest::test_named_urlspec_groups\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_chunked_body\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_compressed_body\nPASSED r2e_tests.test_1::NativeStreamingRequestFlowControlTest::test_flow_control_fixed_body\nPASSED r2e_tests.test_1::NonWSGIWebTests::test_empty_flush\nPASSED r2e_tests.test_1::NonWSGIWebTests::test_flow_control\nPASSED r2e_tests.test_1::PatchMethodTest::test_other\nPASSED r2e_tests.test_1::PatchMethodTest::test_patch\nPASSED r2e_tests.test_1::PathArgsInPrepareTest::test_kw\nPASSED r2e_tests.test_1::PathArgsInPrepareTest::test_pos\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_httperror_str\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_httperror_str_from_httputil\nPASSED r2e_tests.test_1::RaiseWithReasonTest::test_raise_with_reason\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_basic_redirect\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_pattern\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_with_appending_argument\nPASSED r2e_tests.test_1::RedirectHandlerTest::test_redirect_with_argument\nPASSED r2e_tests.test_1::RequestEncodingTest::test_error\nPASSED r2e_tests.test_1::RequestEncodingTest::test_group_encoding\nPASSED r2e_tests.test_1::RequestEncodingTest::test_group_question_mark\nPASSED r2e_tests.test_1::RequestEncodingTest::test_slashes\nPASSED r2e_tests.test_1::RequestSummaryTest::test_missing_remote_ip\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_arbitrary_bytes\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_cookie_tampering_future_timestamp\nPASSED r2e_tests.test_1::SecureCookieV1Test::test_round_trip\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_increment_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_invalidate_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_roundtrip\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_key_version_roundtrip_differing_version\nPASSED r2e_tests.test_1::SecureCookieV2Test::test_round_trip\nPASSED r2e_tests.test_1::SetLazyPropertiesTest::test_set_properties\nPASSED r2e_tests.test_1::SignedValueTest::test_expired\nPASSED r2e_tests.test_1::SignedValueTest::test_key_version_retrieval\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_invalid_key\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_read_write_default_key\nPASSED r2e_tests.test_1::SignedValueTest::test_key_versioning_read_write_non_default_key\nPASSED r2e_tests.test_1::SignedValueTest::test_known_values\nPASSED r2e_tests.test_1::SignedValueTest::test_name_swap\nPASSED r2e_tests.test_1::SignedValueTest::test_non_ascii\nPASSED r2e_tests.test_1::SignedValueTest::test_payload_tampering\nPASSED r2e_tests.test_1::SignedValueTest::test_signature_tampering\nFAILED r2e_tests.test_1::StaticDefaultFilenameTest::test_static_default_filename\nFAILED r2e_tests.test_1::StaticDefaultFilenameTest::test_static_default_redirect\nFAILED r2e_tests.test_1::StaticFileTest::test_absolute_static_url\nPASSED r2e_tests.test_1::StaticFileTest::test_absolute_version_exclusion\nPASSED r2e_tests.test_1::StaticFileTest::test_include_host_override\nPASSED r2e_tests.test_1::StaticFileTest::test_path_traversal_protection\nPASSED r2e_tests.test_1::StaticFileTest::test_relative_version_exclusion\nFAILED r2e_tests.test_1::StaticFileTest::test_root_static_path\nERROR r2e_tests.test_1::StaticFileTest::test_static_304_if_modified_since\nERROR r2e_tests.test_1::StaticFileTest::test_static_304_if_none_match\nPASSED r2e_tests.test_1::StaticFileTest::test_static_404\nFAILED r2e_tests.test_1::StaticFileTest::test_static_compressed_files\nFAILED r2e_tests.test_1::StaticFileTest::test_static_etag\nFAILED r2e_tests.test_1::StaticFileTest::test_static_files\nFAILED r2e_tests.test_1::StaticFileTest::test_static_head\nFAILED r2e_tests.test_1::StaticFileTest::test_static_head_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_if_modified_since_pre_epoch\nERROR r2e_tests.test_1::StaticFileTest::test_static_if_modified_since_time_zone\nFAILED r2e_tests.test_1::StaticFileTest::test_static_invalid_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_range_if_none_match\nFAILED r2e_tests.test_1::StaticFileTest::test_static_unsatisfiable_range_invalid_start\nFAILED r2e_tests.test_1::StaticFileTest::test_static_unsatisfiable_range_zero_suffix\nFAILED r2e_tests.test_1::StaticFileTest::test_static_url\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_end_edge\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_full_file\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_full_past_end\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_neg_end\nFAILED r2e_tests.test_1::StaticFileTest::test_static_with_range_partial_past_end\nFAILED r2e_tests.test_1::StaticFileWithPathTest::test_serve\nPASSED r2e_tests.test_1::StatusReasonTest::test_status\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_close_during_upload\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_early_return\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_early_return_with_data\nPASSED r2e_tests.test_1::StreamingRequestBodyTest::test_streaming_body\nPASSED r2e_tests.test_1::UIMethodUIModuleTest::test_ui_method\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_non_reversible\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_reverse\nPASSED r2e_tests.test_1::URLSpecReverseTest::test_reverse_arguments\nPASSED r2e_tests.test_1::UnimplementedHTTPMethodsTest::test_unimplemented_standard_methods\nPASSED r2e_tests.test_1::UnimplementedNonStandardMethodsTest::test_unimplemented_other\nPASSED r2e_tests.test_1::UnimplementedNonStandardMethodsTest::test_unimplemented_patch\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument_invalid_unicode\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_decode_argument_plus\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_argument\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_body_arguments\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_get_query_arguments\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_header_injection\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_multi_header\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_no_gzip\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_optional_path\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_redirect\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_reverse_url\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_types\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_uimodule_resources\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_uimodule_unescaped\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_web_redirect\nPASSED r2e_tests.test_1::WSGISafeWebTest::test_web_redirect_double_slash\nPASSED r2e_tests.test_1::XSRFCookieKwargsTest::test_xsrf_httponly\nPASSED r2e_tests.test_1::XSRFTest::test_cross_user\nPASSED r2e_tests.test_1::XSRFTest::test_distinct_tokens\nPASSED r2e_tests.test_1::XSRFTest::test_refresh_token\nPASSED r2e_tests.test_1::XSRFTest::test_versioning\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_argument_invalid_format\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_body_no_cookie\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_cookie_invalid_format\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_cookie_no_body\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_fail_no_token\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_header\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_non_hex_token\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_post_body\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_query_string\nPASSED r2e_tests.test_1::XSRFTest::test_xsrf_success_short_token\nERROR r2e_tests.test_2::ChunkedWithContentLengthTest::test_chunked_with_content_length\nPASSED r2e_tests.test_2::CreateAsyncHTTPClientTestCase::test_max_clients\nPASSED r2e_tests.test_2::HTTP100ContinueTestCase::test_100_continue\nSKIPPED r2e_tests.test_2::HTTP204NoContentTestCase::test_204_invalid_content_length\nPASSED r2e_tests.test_2::HTTP204NoContentTestCase::test_204_no_content\nPASSED r2e_tests.test_2::HostnameMappingTestCase::test_hostname_mapping\nPASSED r2e_tests.test_2::HostnameMappingTestCase::test_port_mapping\nERROR r2e_tests.test_2::MaxBodySizeTest::test_large_body\nPASSED r2e_tests.test_2::MaxBodySizeTest::test_small_body\nPASSED r2e_tests.test_2::MaxBufferSizeTest::test_large_body\nERROR r2e_tests.test_2::MaxHeaderSizeTest::test_large_headers\nPASSED r2e_tests.test_2::MaxHeaderSizeTest::test_small_headers\nPASSED r2e_tests.test_2::ResolveTimeoutTestCase::test_resolve_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_304_with_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_all_methods\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_basic_auth\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_basic_auth_explicit_mode\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_body_encoding\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_body_sanity_checks\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_chunked_close\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_configure_defaults\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_credentials_in_url\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_final_callback_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_follow_redirect\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_http_error\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_http_error_no_raise\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_future_interface\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_callback\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_callback_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_header_types\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_hello_world\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_multi_line_headers\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_non_ascii_header\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_patch_receives_payload\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_post\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_put_307\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_reuse_request_from_response\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_streaming_callback\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_streaming_stack_context\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_types\nPASSED r2e_tests.test_2::SimpleHTTPClientCommonTestCase::test_unsupported_auth_mode\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_100_continue\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_100_continue_early_response\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_async_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_async_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connect_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_header_reuse\nFAILED r2e_tests.test_2::SimpleHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_native_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_native_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_no_content_length\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_queue_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_singleton\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_streaming_follow_redirects\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_sync_body_producer_chunked\nPASSED r2e_tests.test_2::SimpleHTTPClientTestCase::test_sync_body_producer_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_100_continue\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_100_continue_early_response\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_async_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_async_body_producer_content_length\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connect_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connection_limit\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_connection_refused\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_error_logging\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_gzip\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_head_request\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_header_reuse\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_host_header\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ipv6\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_max_redirects\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_native_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_native_body_producer_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_no_content\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_no_content_length\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_options_request\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_queue_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_redirect_connection_limit\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_request_timeout\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_2::SimpleHTTPSClientTestCase::test_singleton\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_context\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_context_handshake_fail\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_options\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_ssl_options_handshake_fail\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_streaming_follow_redirects\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_sync_body_producer_chunked\nERROR r2e_tests.test_2::SimpleHTTPSClientTestCase::test_sync_body_producer_content_length\n=================== 25 failed, 34 errors, 219 passed, 2 skipped in 1.75s ===================\n",
    "old_commit_res_stderr": "WARNING:tornado.access:405 HEAD / (127.0.0.1) 0.30ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET / (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 GET / (127.0.0.1) 0.21ms\nWARNING:tornado.access:403 GET / (127.0.0.1) 0.20ms\nWARNING:tornado.access:404 GET /baz (127.0.0.1) 0.20ms\nWARNING:tornado.access:404 GET /foo (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 POST /404 (127.0.0.1) 0.21ms\nWARNING:tornado.access:417 POST /error (127.0.0.1) 0.25ms\nERROR:tornado.access:500 GET /default (127.0.0.1) 0.26ms\nERROR:tornado.access:503 GET /default?status=503 (127.0.0.1) 0.21ms\nWARNING:tornado.access:435 GET /default?status=435 (127.0.0.1) 0.21ms\nERROR:tornado.access:500 GET /failed_write_error (127.0.0.1) 0.28ms\nERROR:tornado.access:500 GET /write_error (127.0.0.1) 0.25ms\nERROR:tornado.access:503 GET /write_error?status=503 (127.0.0.1) 0.20ms\nWARNING:tornado.access:410 GET /?exc=http (127.0.0.1) 0.30ms\nWARNING:tornado.access:403 GET /?exc=permission (127.0.0.1) 0.31ms\nERROR:tornado.access:500 GET /?exc=zero (127.0.0.1) 0.28ms\nWARNING:tornado.access:401 GET / (127.0.0.1) 0.20ms\nWARNING:tornado.access:401 GET /?finish_value=1 (127.0.0.1) 0.20ms\nWARNING:tornado.access:404 GET /robots.txt (127.0.0.1) 0.30ms\nWARNING:tornado.access:404 GET /bar (127.0.0.1) 0.21ms\nWARNING:tornado.access:404 GET /baz (127.0.0.1) 0.20ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.27ms\nERROR:tornado.access:500 GET / (127.0.0.1) 0.27ms\nERROR:tornado.access:682 GET / (127.0.0.1) 0.21ms\nWARNING:tornado.access:400 GET /group/?arg=%25%e9 (127.0.0.1) 0.46ms\nWARNING:tornado.access:404 GET /static/dir/ (127.0.0.1) 0.27ms\nWARNING:tornado.access:404 GET /static/dir (127.0.0.1) 0.25ms\nERROR:tornado.general:Could not open static file '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt'\nWARNING:tornado.access:403 HEAD /static/../static_foo.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:403 GET /static/../static_foo.txt (127.0.0.1) 0.27ms\nWARNING:tornado.access:404 HEAD /root_static/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /root_static/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/r2e_tests/static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 HEAD /static/blarg (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/blarg (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/sample.xml.gz (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.29ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.26ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.25ms\nWARNING:tornado.access:404 HEAD /static/robots.txt (127.0.0.1) 0.42ms\nWARNING:tornado.access:404 GET /static/robots.txt (127.0.0.1) 0.28ms\nWARNING:tornado.access:404 GET /foo/utf8.html (127.0.0.1) 0.29ms\nERROR:tornado.access:682 GET /?code=682&reason=Bar (127.0.0.1) 0.19ms\nERROR:tornado.access:682 GET /?code=682 (127.0.0.1) 0.17ms\nWARNING:tornado.access:401 GET /early_return (127.0.0.1) 0.18ms\nWARNING:tornado.access:401 GET /early_return (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 HEAD / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 GET / (127.0.0.1) 0.21ms\nWARNING:tornado.access:405 DELETE / (127.0.0.1) 0.19ms\nWARNING:tornado.access:405 OPTIONS / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 POST / (127.0.0.1) 0.23ms\nWARNING:tornado.access:405 PUT / (127.0.0.1) 0.20ms\nWARNING:tornado.access:405 OTHER / (127.0.0.1) 0.21ms\nWARNING:tornado.access:405 PATCH / (127.0.0.1) 0.35ms\nWARNING:tornado.access:400 GET /typecheck/invalid%FF (127.0.0.1) 0.29ms\nWARNING:tornado.access:400 GET /typecheck/invalid?foo=%FF (127.0.0.1) 0.25ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.32ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.29ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.33ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.28ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.30ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.27ms\nWARNING:tornado.access:403 POST / (127.0.0.1) 0.25ms\nWARNING:tornado.access:405 HEAD /all_methods (127.0.0.1) 0.24ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.32ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.24ms\nWARNING:tornado.access:403 POST /respond_in_prepare (127.0.0.1) 0.18ms\nERROR:tornado.application:Future <tornado.concurrent.Future object at 0x71c96b4781c0> exception was never retrieved: Traceback (most recent call last):\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/gen.py\", line 303, in wrapper\n    yielded = next(result)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/tcpclient.py\", line 225, in connect\n    addrinfo = yield self.resolver.resolve(host, port, af)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_a42b028ca26150b41ca537f08b06aff3163a682e/tornado/concurrent.py\", line 401, in wrapper\n    future = getattr(self, executor).submit(fn, self, *args, **kwargs)\nAttributeError: 'NoneType' object has no attribute 'submit'\n"
}
tornado/test/simple_httpclient_test.py tornado/test/util.py tornado/test/web_test.py tornado/testing.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Host Header Mismatch Causes Test Failures**

**Description**
When running tests, the host header is set to `'127.0.0.1'` instead of `'localhost'`. This discrepancy causes assertions that expect `'localhost'` to fail.

**Example Buggy Code**
```python
host_re = re.compile(b"^localhost:[0-9]+$")
response = self.fetch("/host_echo")
self.assertTrue(host_re.match(response.body))
```
In this code, the regular expression expects the host to start with `'localhost'`, but the actual response contains `'127.0.0.1'`, leading to a mismatch.

**Expected Behavior**
The host header should match `'localhost'` as specified in the test, ensuring that the regular expression validation passes.

**Actual Behavior**
The host header contains `'127.0.0.1'`, which does not satisfy the regular expression `^localhost:[0-9]+$`, resulting in failed assertions.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/testing.py
#!/usr/bin/env python
"""Support classes for automated testing.

* `AsyncTestCase` and `AsyncHTTPTestCase`:  Subclasses of unittest.TestCase
  with additional support for testing asynchronous (`.IOLoop`-based) code.

* `ExpectLog`: Make test logs less spammy.

* `main()`: A simple test runner (wrapper around unittest.main()) with support
  for the tornado.autoreload module to rerun the tests when code changes.
"""

from __future__ import absolute_import, division, print_function

try:
    from tornado import gen
    from tornado.httpclient import AsyncHTTPClient
    from tornado.httpserver import HTTPServer
    from tornado.simple_httpclient import SimpleAsyncHTTPClient
    from tornado.ioloop import IOLoop, TimeoutError
    from tornado import netutil
    from tornado.process import Subprocess
except ImportError:
    # These modules are not importable on app engine.  Parts of this module
    # won't work, but e.g. main() will.
    AsyncHTTPClient = None  # type: ignore
    gen = None  # type: ignore
    HTTPServer = None  # type: ignore
    IOLoop = None  # type: ignore
    netutil = None  # type: ignore
    SimpleAsyncHTTPClient = None  # type: ignore
    Subprocess = None  # type: ignore
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

if PY3:
    from io import StringIO
else:
    from cStringIO import StringIO

try:
    from collections.abc import Generator as GeneratorType  # type: ignore
except ImportError:
    from types import GeneratorType  # type: ignore

if sys.version_info >= (3, 5):
    iscoroutine = inspect.iscoroutine  # type: ignore
    iscoroutinefunction = inspect.iscoroutinefunction  # type: ignore
else:
    iscoroutine = iscoroutinefunction = lambda f: False

# Tornado's own test suite requires the updated unittest module
# (either py27+ or unittest2) so tornado.test.util enforces
# this requirement, but for other users of tornado.testing we want
# to allow the older version if unitest2 is not available.
if PY3:
    # On python 3, mixing unittest2 and unittest (including doctest)
    # doesn't seem to work, so always use unittest.
    import unittest
else:
    # On python 2, prefer unittest2 when available.
    try:
        import unittest2 as unittest  # type: ignore
    except ImportError:
        import unittest  # type: ignore


def bind_unused_port(reuse_port=False):
    """Binds a server socket to an available port on localhost.

    Returns a tuple (socket, port).

    .. versionchanged:: 4.4
       Always binds to ``127.0.0.1`` without resolving the name
       ``localhost``.
    """
    sock = netutil.bind_sockets(None, '127.0.0.1', family=socket.AF_INET,
                                reuse_port=reuse_port)[0]
    port = sock.getsockname()[1]
    return sock, port


def get_async_test_timeout():
    """Get the global timeout setting for async tests.

    Returns a float, the timeout in seconds.

    .. versionadded:: 3.1
    """
    try:
        return float(os.environ.get('ASYNC_TEST_TIMEOUT'))
    except (ValueError, TypeError):
        return 5


class _TestMethodWrapper(object):
    """Wraps a test method to raise an error if it returns a value.

    This is mainly used to detect undecorated generators (if a test
    method yields it must use a decorator to consume the generator),
    but will also detect other kinds of return values (these are not
    necessarily errors, but we alert anyway since there is no good
    reason to return a value from a test).
    """
    def __init__(self, orig_method):
        self.orig_method = orig_method

    def __call__(self, *args, **kwargs):
        result = self.orig_method(*args, **kwargs)
        if isinstance(result, GeneratorType) or iscoroutine(result):
            raise TypeError("Generator and coroutine test methods should be"
                            " decorated with tornado.testing.gen_test")
        elif result is not None:
            raise ValueError("Return value from test method ignored: %r" %
                             result)

    def __getattr__(self, name):
        """Proxy all unknown attributes to the original method.

        This is important for some of the decorators in the `unittest`
        module, such as `unittest.skipIf`.
        """
        return getattr(self.orig_method, name)


class AsyncTestCase(unittest.TestCase):
    """`~unittest.TestCase` subclass for testing `.IOLoop`-based
    asynchronous code.

    The unittest framework is synchronous, so the test must be
    complete by the time the test method returns.  This means that
    asynchronous code cannot be used in quite the same way as usual.
    To write test functions that use the same ``yield``-based patterns
    used with the `tornado.gen` module, decorate your test methods
    with `tornado.testing.gen_test` instead of
    `tornado.gen.coroutine`.  This class also provides the `stop()`
    and `wait()` methods for a more manual style of testing.  The test
    method itself must call ``self.wait()``, and asynchronous
    callbacks should call ``self.stop()`` to signal completion.

    By default, a new `.IOLoop` is constructed for each test and is available
    as ``self.io_loop``.  If the code being tested requires a
    global `.IOLoop`, subclasses should override `get_new_ioloop` to return it.

    The `.IOLoop`'s ``start`` and ``stop`` methods should not be
    called directly.  Instead, use `self.stop <stop>` and `self.wait
    <wait>`.  Arguments passed to ``self.stop`` are returned from
    ``self.wait``.  It is possible to have multiple ``wait``/``stop``
    cycles in the same test.

    Example::

        # This test uses coroutine style.
        class MyTestCase(AsyncTestCase):
            @tornado.testing.gen_test
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                response = yield client.fetch("http://www.tornadoweb.org")
                # Test contents of response
                self.assertIn("FriendFeed", response.body)

        # This test uses argument passing between self.stop and self.wait.
        class MyTestCase2(AsyncTestCase):
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                client.fetch("http://www.tornadoweb.org/", self.stop)
                response = self.wait()
                # Test contents of response
                self.assertIn("FriendFeed", response.body)

        # This test uses an explicit callback-based style.
        class MyTestCase3(AsyncTestCase):
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                client.fetch("http://www.tornadoweb.org/", self.handle_fetch)
                self.wait()

            def handle_fetch(self, response):
                # Test contents of response (failures and exceptions here
                # will cause self.wait() to throw an exception and end the
                # test).
                # Exceptions thrown here are magically propagated to
                # self.wait() in test_http_fetch() via stack_context.
                self.assertIn("FriendFeed", response.body)
                self.stop()
    """
    def __init__(self, methodName='runTest'):
        super(AsyncTestCase, self).__init__(methodName)
        self.__stopped = False
        self.__running = False
        self.__failure = None
        self.__stop_args = None
        self.__timeout = None

        # It's easy to forget the @gen_test decorator, but if you do
        # the test will silently be ignored because nothing will consume
        # the generator.  Replace the test method with a wrapper that will
        # make sure it's not an undecorated generator.
        setattr(self, methodName, _TestMethodWrapper(getattr(self, methodName)))

    def setUp(self):
        super(AsyncTestCase, self).setUp()
        self.io_loop = self.get_new_ioloop()
        self.io_loop.make_current()

    def tearDown(self):
        # Clean up Subprocess, so it can be used again with a new ioloop.
        Subprocess.uninitialize()
        self.io_loop.clear_current()
        # Try to clean up any file descriptors left open in the ioloop.
        # This avoids leaks, especially when tests are run repeatedly
        # in the same process with autoreload (because curl does not
        # set FD_CLOEXEC on its file descriptors)
        self.io_loop.close(all_fds=True)
        super(AsyncTestCase, self).tearDown()
        # In case an exception escaped or the StackContext caught an exception
        # when there wasn't a wait() to re-raise it, do so here.
        # This is our last chance to raise an exception in a way that the
        # unittest machinery understands.
        self.__rethrow()

    def get_new_ioloop(self):
        """Creates a new `.IOLoop` for this test.  May be overridden in
        subclasses for tests that require a specific `.IOLoop` (usually
        the singleton `.IOLoop.instance()`).
        """
        return IOLoop()

    def _handle_exception(self, typ, value, tb):
        if self.__failure is None:
            self.__failure = (typ, value, tb)
        else:
            app_log.error("multiple unhandled exceptions in test",
                          exc_info=(typ, value, tb))
        self.stop()
        return True

    def __rethrow(self):
        if self.__failure is not None:
            failure = self.__failure
            self.__failure = None
            raise_exc_info(failure)

    def run(self, result=None):
        with ExceptionStackContext(self._handle_exception):
            super(AsyncTestCase, self).run(result)
        # As a last resort, if an exception escaped super.run() and wasn't
        # re-raised in tearDown, raise it here.  This will cause the
        # unittest run to fail messily, but that's better than silently
        # ignoring an error.
        self.__rethrow()

    def stop(self, _arg=None, **kwargs):
        """Stops the `.IOLoop`, causing one pending (or future) call to `wait()`
        to return.

        Keyword arguments or a single positional argument passed to `stop()` are
        saved and will be returned by `wait()`.
        """
        assert _arg is None or not kwargs
        self.__stop_args = kwargs or _arg
        if self.__running:
            self.io_loop.stop()
            self.__running = False
        self.__stopped = True

    def wait(self, condition=None, timeout=None):
        """Runs the `.IOLoop` until stop is called or timeout has passed.

        In the event of a timeout, an exception will be thrown. The
        default timeout is 5 seconds; it may be overridden with a
        ``timeout`` keyword argument or globally with the
        ``ASYNC_TEST_TIMEOUT`` environment variable.

        If ``condition`` is not None, the `.IOLoop` will be restarted
        after `stop()` until ``condition()`` returns true.

        .. versionchanged:: 3.1
           Added the ``ASYNC_TEST_TIMEOUT`` environment variable.
        """
        if timeout is None:
            timeout = get_async_test_timeout()

        if not self.__stopped:
            if timeout:
                def timeout_func():
                    try:
                        raise self.failureException(
                            'Async operation timed out after %s seconds' %
                            timeout)
                    except Exception:
                        self.__failure = sys.exc_info()
                    self.stop()
                self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func)
            while True:
                self.__running = True
                self.io_loop.start()
                if (self.__failure is not None or
                        condition is None or condition()):
                    break
            if self.__timeout is not None:
                self.io_loop.remove_timeout(self.__timeout)
                self.__timeout = None
        assert self.__stopped
        self.__stopped = False
        self.__rethrow()
        result = self.__stop_args
        self.__stop_args = None
        return result


class AsyncHTTPTestCase(AsyncTestCase):
    """A test case that starts up an HTTP server.

    Subclasses must override `get_app()`, which returns the
    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.
    Tests will typically use the provided ``self.http_client`` to fetch
    URLs from this server.

    Example, assuming the "Hello, world" example from the user guide is in
    ``hello.py``::

        import hello

        class TestHelloApp(AsyncHTTPTestCase):
            def get_app(self):
                return hello.make_app()

            def test_homepage(self):
                response = self.fetch('/')
                self.assertEqual(response.code, 200)
                self.assertEqual(response.body, 'Hello, world')

    That call to ``self.fetch()`` is equivalent to ::

        self.http_client.fetch(self.get_url('/'), self.stop)
        response = self.wait()

    which illustrates how AsyncTestCase can turn an asynchronous operation,
    like ``http_client.fetch()``, into a synchronous operation. If you need
    to do other asynchronous operations in tests, you'll probably need to use
    ``stop()`` and ``wait()`` yourself.
    """
    def setUp(self):
        super(AsyncHTTPTestCase, self).setUp()
        sock, port = bind_unused_port()
        self.__port = port

        self.http_client = self.get_http_client()
        self._app = self.get_app()
        self.http_server = self.get_http_server()
        self.http_server.add_sockets([sock])

    def get_http_client(self):
        return AsyncHTTPClient()

    def get_http_server(self):
        return HTTPServer(self._app, **self.get_httpserver_options())

    def get_app(self):
        """Should be overridden by subclasses to return a
        `tornado.web.Application` or other `.HTTPServer` callback.
        """
        raise NotImplementedError()

    def fetch(self, path, **kwargs):
        """Convenience method to synchronously fetch a URL.

        The given path will be appended to the local server's host and
        port.  Any additional kwargs will be passed directly to
        `.AsyncHTTPClient.fetch` (and so could be used to pass
        ``method="POST"``, ``body="..."``, etc).

        If the path begins with http:// or https://, it will be treated as a
        full URL and will be fetched as-is.
        """
        if path.lower().startswith(('http://', 'https://')):
            self.http_client.fetch(path, self.stop, **kwargs)
        else:
            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)
        return self.wait()

    def get_httpserver_options(self):
        """May be overridden by subclasses to return additional
        keyword arguments for the server.
        """
        return {}

    def get_http_port(self):
        """Returns the port used by the server.

        A new port is chosen for each test.
        """
        return self.__port

    def get_protocol(self):
        return 'http'

    def get_url(self, path):
        """Returns an absolute url for the given path on the test server."""
        return '%s://localhost:%s%s' % (self.get_protocol(),
                                        self.get_http_port(), path)

    def tearDown(self):
        self.http_server.stop()
        self.io_loop.run_sync(self.http_server.close_all_connections,
                              timeout=get_async_test_timeout())
        self.http_client.close()
        super(AsyncHTTPTestCase, self).tearDown()


class AsyncHTTPSTestCase(AsyncHTTPTestCase):
    """A test case that starts an HTTPS server.

    Interface is generally the same as `AsyncHTTPTestCase`.
    """
    def get_http_client(self):
        return AsyncHTTPClient(force_instance=True,
                               defaults=dict(validate_cert=False))

    def get_httpserver_options(self):
        return dict(ssl_options=self.get_ssl_options())

    def get_ssl_options(self):
        """May be overridden by subclasses to select SSL options.

        By default includes a self-signed testing certificate.
        """
        # Testing keys were generated with:
        # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509
        module_dir = os.path.dirname(__file__)
        return dict(
            certfile=os.path.join(module_dir, 'test', 'test.crt'),
            keyfile=os.path.join(module_dir, 'test', 'test.key'))

    def get_protocol(self):
        return 'https'


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 self.http_client.fetch(self.get_url('/'))

    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 self.http_client.fetch(self.get_url('/'))

    Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`,
    `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield
    self.http_client.fetch(self.get_url())`` as shown above instead.

    .. 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


# Without this attribute, nosetests will try to run gen_test as a test
# anywhere it is imported.
gen_test.__test__ = False  # type: ignore


class ExpectLog(logging.Filter):
    """Context manager to capture and suppress expected log output.

    Useful to make tests of error conditions less noisy, while still
    leaving unexpected log entries visible.  *Not thread safe.*

    The attribute ``logged_stack`` is set to true if any exception
    stack trace was logged.

    Usage::

        with ExpectLog('tornado.application', "Uncaught exception"):
            error_response = self.fetch("/some_page")

    .. versionchanged:: 4.3
       Added the ``logged_stack`` attribute.
    """
    def __init__(self, logger, regex, required=True):
        """Constructs an ExpectLog context manager.

        :param logger: Logger object (or name of logger) to watch.  Pass
            an empty string to watch the root logger.
        :param regex: Regular expression to match.  Any log entries on
            the specified logger that match this regex will be suppressed.
        :param required: If true, an exception will be raised if the end of
            the ``with`` statement is reached without matching any log entries.
        """
        if isinstance(logger, basestring_type):
            logger = logging.getLogger(logger)
        self.logger = logger
        self.regex = re.compile(regex)
        self.required = required
        self.matched = False
        self.logged_stack = False

    def filter(self, record):
        if record.exc_info:
            self.logged_stack = True
        message = record.getMessage()
        if self.regex.match(message):
            self.matched = True
            return False
        return True

    def __enter__(self):
        self.logger.addFilter(self)
        return self

    def __exit__(self, typ, value, tb):
        self.logger.removeFilter(self)
        if not typ and self.required and not self.matched:
            raise Exception("did not get expected log message")


def main(**kwargs):
    """A simple test runner.

    This test runner is essentially equivalent to `unittest.main` from
    the standard library, but adds support for tornado-style option
    parsing and log formatting. It is *not* necessary to use this
    `main` function to run tests using `AsyncTestCase`; these tests
    are self-contained and can run with any test runner.

    The easiest way to run a test is via the command line::

        python -m tornado.testing tornado.test.stack_context_test

    See the standard library unittest module for ways in which tests can
    be specified.

    Projects with many tests may wish to define a test script like
    ``tornado/test/runtests.py``.  This script should define a method
    ``all()`` which returns a test suite and then call
    `tornado.testing.main()`.  Note that even when a test script is
    used, the ``all()`` test suite may be overridden by naming a
    single test on the command line::

        # Runs all tests
        python -m tornado.test.runtests
        # Runs one test
        python -m tornado.test.runtests tornado.test.stack_context_test

    Additional keyword arguments passed through to ``unittest.main()``.
    For example, use ``tornado.testing.main(verbosity=2)``
    to show many test details as they are run.
    See http://docs.python.org/library/unittest.html#unittest.main
    for full argument list.
    """
    from tornado.options import define, options, parse_command_line

    define('exception_on_interrupt', type=bool, default=True,
           help=("If true (default), ctrl-c raises a KeyboardInterrupt "
                 "exception.  This prints a stack trace but cannot interrupt "
                 "certain operations.  If false, the process is more reliably "
                 "killed, but does not print a stack trace."))

    # support the same options as unittest's command-line interface
    define('verbose', type=bool)
    define('quiet', type=bool)
    define('failfast', type=bool)
    define('catch', type=bool)
    define('buffer', type=bool)

    argv = [sys.argv[0]] + parse_command_line(sys.argv)

    if not options.exception_on_interrupt:
        signal.signal(signal.SIGINT, signal.SIG_DFL)

    if options.verbose is not None:
        kwargs['verbosity'] = 2
    if options.quiet is not None:
        kwargs['verbosity'] = 0
    if options.failfast is not None:
        kwargs['failfast'] = True
    if options.catch is not None:
        kwargs['catchbreak'] = True
    if options.buffer is not None:
        kwargs['buffer'] = True

    if __name__ == '__main__' and len(argv) == 1:
        print("No tests specified", file=sys.stderr)
        sys.exit(1)
    try:
        # In order to be able to run tests by their fully-qualified name
        # on the command line without importing all tests here,
        # module must be set to None.  Python 3.2's unittest.main ignores
        # defaultTest if no module is given (it tries to do its own
        # test discovery, which is incompatible with auto2to3), so don't
        # set module if we're not asking for a specific test.
        if len(argv) > 1:
            unittest.main(module=None, argv=argv, **kwargs)
        else:
            unittest.main(defaultTest="all", argv=argv, **kwargs)
    except SystemExit as e:
        if e.code == 0:
            gen_log.info('PASS')
        else:
            gen_log.error('FAIL')
        raise


if __name__ == '__main__':
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Host Header Mismatch Causes Test Failures**

**Description**
When running tests, the host header is set to `'127.0.0.1'` instead of `'localhost'`. This discrepancy causes assertions that expect `'localhost'` to fail.

**Example Buggy Code**
```python
host_re = re.compile(b"^localhost:[0-9]+$")
response = self.fetch("/host_echo")
self.assertTrue(host_re.match(response.body))
```
In this code, the regular expression expects the host to start with `'localhost'`, but the actual response contains `'127.0.0.1'`, leading to a mismatch.

**Expected Behavior**
The host header should match `'localhost'` as specified in the test, ensuring that the regular expression validation passes.

**Actual Behavior**
The host header contains `'127.0.0.1'`, which does not satisfy the regular expression `^localhost:[0-9]+$`, resulting in failed assertions.

[/ISSUE]
{
    "AllHTTPMethodsTest.test_standard_methods": "PASSED",
    "ApplicationTest.test_listen": "PASSED",
    "AuthRedirectTest.test_absolute_auth_redirect": "PASSED",
    "AuthRedirectTest.test_relative_auth_redirect": "PASSED",
    "BuggyLoggingTest.test_buggy_log_exception": "PASSED",
    "CacheTest.test_multiple_strong_etag_match": "PASSED",
    "CacheTest.test_multiple_strong_etag_not_match": "PASSED",
    "CacheTest.test_multiple_weak_etag_match": "PASSED",
    "CacheTest.test_multiple_weak_etag_not_match": "PASSED",
    "CacheTest.test_strong_etag_match": "PASSED",
    "CacheTest.test_strong_etag_not_match": "PASSED",
    "CacheTest.test_weak_etag_match": "PASSED",
    "CacheTest.test_weak_etag_not_match": "PASSED",
    "CacheTest.test_wildcard_etag": "PASSED",
    "ClearAllCookiesTest.test_clear_all_cookies": "PASSED",
    "ClearHeaderTest.test_clear_header": "PASSED",
    "ClientCloseTest.test_client_close": "PASSED",
    "ConnectionCloseTest.test_connection_close": "PASSED",
    "CookieTest.test_cookie_special_char": "PASSED",
    "CookieTest.test_get_cookie": "PASSED",
    "CookieTest.test_set_cookie": "PASSED",
    "CookieTest.test_set_cookie_domain": "PASSED",
    "CookieTest.test_set_cookie_expires_days": "PASSED",
    "CookieTest.test_set_cookie_false_flags": "PASSED",
    "CookieTest.test_set_cookie_max_age": "PASSED",
    "CookieTest.test_set_cookie_overwrite": "PASSED",
    "Custom404Test.test_404": "PASSED",
    "CustomStaticFileTest.test_serve": "PASSED",
    "CustomStaticFileTest.test_static_url": "PASSED",
    "DateHeaderTest.test_date_header": "PASSED",
    "DecoratedStreamingRequestFlowControlTest.test_flow_control_chunked_body": "PASSED",
    "DecoratedStreamingRequestFlowControlTest.test_flow_control_compressed_body": "PASSED",
    "DecoratedStreamingRequestFlowControlTest.test_flow_control_fixed_body": "PASSED",
    "DecoratorTest.test_addslash": "PASSED",
    "DecoratorTest.test_removeslash": "PASSED",
    "Default404Test.test_404": "PASSED",
    "DefaultHandlerArgumentsTest.test_403": "PASSED",
    "DefaultHostMatchingTest.test_default_host_matching": "PASSED",
    "ErrorHandlerXSRFTest.test_404_xsrf": "PASSED",
    "ErrorHandlerXSRFTest.test_error_xsrf": "PASSED",
    "ErrorResponseTest.test_default": "PASSED",
    "ErrorResponseTest.test_failed_write_error": "PASSED",
    "ErrorResponseTest.test_write_error": "PASSED",
    "ExceptionHandlerTest.test_http_error": "PASSED",
    "ExceptionHandlerTest.test_known_error": "PASSED",
    "ExceptionHandlerTest.test_unknown_error": "PASSED",
    "FinishExceptionTest.test_finish_exception": "PASSED",
    "FinishInPrepareTest.test_finish_in_prepare": "PASSED",
    "GetArgumentErrorTest.test_catch_error": "PASSED",
    "GetCurrentUserTest.test_get_current_user_from_ui_module_is_lazy": "PASSED",
    "GetCurrentUserTest.test_get_current_user_from_ui_module_works": "PASSED",
    "GetCurrentUserTest.test_get_current_user_works": "PASSED",
    "GzipTestCase.test_gzip": "PASSED",
    "GzipTestCase.test_gzip_not_requested": "PASSED",
    "GzipTestCase.test_gzip_static": "FAILED",
    "GzipTestCase.test_vary_already_present": "PASSED",
    "GzipTestCase.test_vary_already_present_multiple": "PASSED",
    "HTTPErrorTest.test_copy": "PASSED",
    "HandlerByNameTest.test_handler_by_name": "PASSED",
    "Header204Test.test_204_headers": "PASSED",
    "Header304Test.test_304_headers": "PASSED",
    "HostMatchingTest.test_host_matching": "PASSED",
    "IncorrectContentLengthTest.test_content_length_too_high": "PASSED",
    "IncorrectContentLengthTest.test_content_length_too_low": "PASSED",
    "MultipleExceptionTest.test_multi_exception": "PASSED",
    "NamedURLSpecGroupsTest.test_named_urlspec_groups": "PASSED",
    "NativeStreamingRequestFlowControlTest.test_flow_control_chunked_body": "PASSED",
    "NativeStreamingRequestFlowControlTest.test_flow_control_compressed_body": "PASSED",
    "NativeStreamingRequestFlowControlTest.test_flow_control_fixed_body": "PASSED",
    "NonWSGIWebTests.test_empty_flush": "PASSED",
    "NonWSGIWebTests.test_flow_control": "PASSED",
    "PatchMethodTest.test_other": "PASSED",
    "PatchMethodTest.test_patch": "PASSED",
    "PathArgsInPrepareTest.test_kw": "PASSED",
    "PathArgsInPrepareTest.test_pos": "PASSED",
    "RaiseWithReasonTest.test_httperror_str": "PASSED",
    "RaiseWithReasonTest.test_httperror_str_from_httputil": "PASSED",
    "RaiseWithReasonTest.test_raise_with_reason": "PASSED",
    "RedirectHandlerTest.test_basic_redirect": "PASSED",
    "RedirectHandlerTest.test_redirect_pattern": "PASSED",
    "RedirectHandlerTest.test_redirect_with_appending_argument": "PASSED",
    "RedirectHandlerTest.test_redirect_with_argument": "PASSED",
    "RequestEncodingTest.test_error": "PASSED",
    "RequestEncodingTest.test_group_encoding": "PASSED",
    "RequestEncodingTest.test_group_question_mark": "PASSED",
    "RequestEncodingTest.test_slashes": "PASSED",
    "RequestSummaryTest.test_missing_remote_ip": "PASSED",
    "SecureCookieV1Test.test_arbitrary_bytes": "PASSED",
    "SecureCookieV1Test.test_cookie_tampering_future_timestamp": "PASSED",
    "SecureCookieV1Test.test_round_trip": "PASSED",
    "SecureCookieV2Test.test_key_version_increment_version": "PASSED",
    "SecureCookieV2Test.test_key_version_invalidate_version": "PASSED",
    "SecureCookieV2Test.test_key_version_roundtrip": "PASSED",
    "SecureCookieV2Test.test_key_version_roundtrip_differing_version": "PASSED",
    "SecureCookieV2Test.test_round_trip": "PASSED",
    "SetLazyPropertiesTest.test_set_properties": "PASSED",
    "SignedValueTest.test_expired": "PASSED",
    "SignedValueTest.test_key_version_retrieval": "PASSED",
    "SignedValueTest.test_key_versioning_invalid_key": "PASSED",
    "SignedValueTest.test_key_versioning_read_write_default_key": "PASSED",
    "SignedValueTest.test_key_versioning_read_write_non_default_key": "PASSED",
    "SignedValueTest.test_known_values": "PASSED",
    "SignedValueTest.test_name_swap": "PASSED",
    "SignedValueTest.test_non_ascii": "PASSED",
    "SignedValueTest.test_payload_tampering": "PASSED",
    "SignedValueTest.test_signature_tampering": "PASSED",
    "StaticDefaultFilenameTest.test_static_default_filename": "FAILED",
    "StaticDefaultFilenameTest.test_static_default_redirect": "FAILED",
    "StaticFileTest.test_absolute_static_url": "FAILED",
    "StaticFileTest.test_absolute_version_exclusion": "PASSED",
    "StaticFileTest.test_include_host_override": "PASSED",
    "StaticFileTest.test_path_traversal_protection": "PASSED",
    "StaticFileTest.test_relative_version_exclusion": "PASSED",
    "StaticFileTest.test_root_static_path": "FAILED",
    "StaticFileTest.test_static_304_if_modified_since": "ERROR",
    "StaticFileTest.test_static_304_if_none_match": "ERROR",
    "StaticFileTest.test_static_404": "PASSED",
    "StaticFileTest.test_static_compressed_files": "FAILED",
    "StaticFileTest.test_static_etag": "FAILED",
    "StaticFileTest.test_static_files": "FAILED",
    "StaticFileTest.test_static_head": "FAILED",
    "StaticFileTest.test_static_head_range": "FAILED",
    "StaticFileTest.test_static_if_modified_since_pre_epoch": "FAILED",
    "StaticFileTest.test_static_if_modified_since_time_zone": "ERROR",
    "StaticFileTest.test_static_invalid_range": "FAILED",
    "StaticFileTest.test_static_range_if_none_match": "FAILED",
    "StaticFileTest.test_static_unsatisfiable_range_invalid_start": "FAILED",
    "StaticFileTest.test_static_unsatisfiable_range_zero_suffix": "FAILED",
    "StaticFileTest.test_static_url": "FAILED",
    "StaticFileTest.test_static_with_range": "FAILED",
    "StaticFileTest.test_static_with_range_end_edge": "FAILED",
    "StaticFileTest.test_static_with_range_full_file": "FAILED",
    "StaticFileTest.test_static_with_range_full_past_end": "FAILED",
    "StaticFileTest.test_static_with_range_neg_end": "FAILED",
    "StaticFileTest.test_static_with_range_partial_past_end": "FAILED",
    "StaticFileWithPathTest.test_serve": "FAILED",
    "StatusReasonTest.test_status": "PASSED",
    "StreamingRequestBodyTest.test_close_during_upload": "PASSED",
    "StreamingRequestBodyTest.test_early_return": "PASSED",
    "StreamingRequestBodyTest.test_early_return_with_data": "PASSED",
    "StreamingRequestBodyTest.test_streaming_body": "PASSED",
    "UIMethodUIModuleTest.test_ui_method": "PASSED",
    "URLSpecReverseTest.test_non_reversible": "PASSED",
    "URLSpecReverseTest.test_reverse": "PASSED",
    "URLSpecReverseTest.test_reverse_arguments": "PASSED",
    "UnimplementedHTTPMethodsTest.test_unimplemented_standard_methods": "PASSED",
    "UnimplementedNonStandardMethodsTest.test_unimplemented_other": "PASSED",
    "UnimplementedNonStandardMethodsTest.test_unimplemented_patch": "PASSED",
    "WSGISafeWebTest.test_decode_argument": "PASSED",
    "WSGISafeWebTest.test_decode_argument_invalid_unicode": "PASSED",
    "WSGISafeWebTest.test_decode_argument_plus": "PASSED",
    "WSGISafeWebTest.test_get_argument": "PASSED",
    "WSGISafeWebTest.test_get_body_arguments": "PASSED",
    "WSGISafeWebTest.test_get_query_arguments": "PASSED",
    "WSGISafeWebTest.test_header_injection": "PASSED",
    "WSGISafeWebTest.test_multi_header": "PASSED",
    "WSGISafeWebTest.test_no_gzip": "PASSED",
    "WSGISafeWebTest.test_optional_path": "PASSED",
    "WSGISafeWebTest.test_redirect": "PASSED",
    "WSGISafeWebTest.test_reverse_url": "PASSED",
    "WSGISafeWebTest.test_types": "PASSED",
    "WSGISafeWebTest.test_uimodule_resources": "PASSED",
    "WSGISafeWebTest.test_uimodule_unescaped": "PASSED",
    "WSGISafeWebTest.test_web_redirect": "PASSED",
    "WSGISafeWebTest.test_web_redirect_double_slash": "PASSED",
    "XSRFCookieKwargsTest.test_xsrf_httponly": "PASSED",
    "XSRFTest.test_cross_user": "PASSED",
    "XSRFTest.test_distinct_tokens": "PASSED",
    "XSRFTest.test_refresh_token": "PASSED",
    "XSRFTest.test_versioning": "PASSED",
    "XSRFTest.test_xsrf_fail_argument_invalid_format": "PASSED",
    "XSRFTest.test_xsrf_fail_body_no_cookie": "PASSED",
    "XSRFTest.test_xsrf_fail_cookie_invalid_format": "PASSED",
    "XSRFTest.test_xsrf_fail_cookie_no_body": "PASSED",
    "XSRFTest.test_xsrf_fail_no_token": "PASSED",
    "XSRFTest.test_xsrf_success_header": "PASSED",
    "XSRFTest.test_xsrf_success_non_hex_token": "PASSED",
    "XSRFTest.test_xsrf_success_post_body": "PASSED",
    "XSRFTest.test_xsrf_success_query_string": "PASSED",
    "XSRFTest.test_xsrf_success_short_token": "PASSED",
    "ChunkedWithContentLengthTest.test_chunked_with_content_length": "ERROR",
    "CreateAsyncHTTPClientTestCase.test_max_clients": "PASSED",
    "HTTP100ContinueTestCase.test_100_continue": "PASSED",
    "HTTP204NoContentTestCase.test_204_no_content": "PASSED",
    "HostnameMappingTestCase.test_hostname_mapping": "PASSED",
    "HostnameMappingTestCase.test_port_mapping": "PASSED",
    "MaxBodySizeTest.test_large_body": "ERROR",
    "MaxBodySizeTest.test_small_body": "PASSED",
    "MaxBufferSizeTest.test_large_body": "PASSED",
    "MaxHeaderSizeTest.test_large_headers": "ERROR",
    "MaxHeaderSizeTest.test_small_headers": "PASSED",
    "ResolveTimeoutTestCase.test_resolve_timeout": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_304_with_content_length": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_all_methods": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_basic_auth": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_basic_auth_explicit_mode": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_body_encoding": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_body_sanity_checks": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_chunked": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_chunked_close": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_configure_defaults": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_credentials_in_url": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_final_callback_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_follow_redirect": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_future_http_error": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_future_http_error_no_raise": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_future_interface": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_header_callback": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_header_callback_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_header_types": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_hello_world": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_multi_line_headers": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_non_ascii_header": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_patch_receives_payload": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_post": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_put_307": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_reuse_request_from_response": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_streaming_callback": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_streaming_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_types": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_unsupported_auth_mode": "PASSED",
    "SimpleHTTPClientTestCase.test_100_continue": "PASSED",
    "SimpleHTTPClientTestCase.test_100_continue_early_response": "PASSED",
    "SimpleHTTPClientTestCase.test_async_body_producer_chunked": "PASSED",
    "SimpleHTTPClientTestCase.test_async_body_producer_content_length": "PASSED",
    "SimpleHTTPClientTestCase.test_connect_timeout": "PASSED",
    "SimpleHTTPClientTestCase.test_connection_limit": "PASSED",
    "SimpleHTTPClientTestCase.test_connection_refused": "PASSED",
    "SimpleHTTPClientTestCase.test_gzip": "PASSED",
    "SimpleHTTPClientTestCase.test_head_request": "PASSED",
    "SimpleHTTPClientTestCase.test_header_reuse": "PASSED",
    "SimpleHTTPClientTestCase.test_host_header": "PASSED",
    "SimpleHTTPClientTestCase.test_ipv6": "PASSED",
    "SimpleHTTPClientTestCase.test_max_redirects": "PASSED",
    "SimpleHTTPClientTestCase.test_native_body_producer_chunked": "PASSED",
    "SimpleHTTPClientTestCase.test_native_body_producer_content_length": "PASSED",
    "SimpleHTTPClientTestCase.test_no_content": "PASSED",
    "SimpleHTTPClientTestCase.test_no_content_length": "PASSED",
    "SimpleHTTPClientTestCase.test_options_request": "PASSED",
    "SimpleHTTPClientTestCase.test_queue_timeout": "PASSED",
    "SimpleHTTPClientTestCase.test_redirect_connection_limit": "PASSED",
    "SimpleHTTPClientTestCase.test_request_timeout": "PASSED",
    "SimpleHTTPClientTestCase.test_see_other_redirect": "PASSED",
    "SimpleHTTPClientTestCase.test_singleton": "PASSED",
    "SimpleHTTPClientTestCase.test_streaming_follow_redirects": "PASSED",
    "SimpleHTTPClientTestCase.test_sync_body_producer_chunked": "PASSED",
    "SimpleHTTPClientTestCase.test_sync_body_producer_content_length": "PASSED",
    "SimpleHTTPSClientTestCase.test_100_continue": "ERROR",
    "SimpleHTTPSClientTestCase.test_100_continue_early_response": "ERROR",
    "SimpleHTTPSClientTestCase.test_async_body_producer_chunked": "ERROR",
    "SimpleHTTPSClientTestCase.test_async_body_producer_content_length": "ERROR",
    "SimpleHTTPSClientTestCase.test_connect_timeout": "PASSED",
    "SimpleHTTPSClientTestCase.test_connection_limit": "ERROR",
    "SimpleHTTPSClientTestCase.test_connection_refused": "PASSED",
    "SimpleHTTPSClientTestCase.test_error_logging": "ERROR",
    "SimpleHTTPSClientTestCase.test_gzip": "ERROR",
    "SimpleHTTPSClientTestCase.test_head_request": "ERROR",
    "SimpleHTTPSClientTestCase.test_header_reuse": "ERROR",
    "SimpleHTTPSClientTestCase.test_host_header": "ERROR",
    "SimpleHTTPSClientTestCase.test_ipv6": "ERROR",
    "SimpleHTTPSClientTestCase.test_max_redirects": "ERROR",
    "SimpleHTTPSClientTestCase.test_native_body_producer_chunked": "ERROR",
    "SimpleHTTPSClientTestCase.test_native_body_producer_content_length": "ERROR",
    "SimpleHTTPSClientTestCase.test_no_content": "ERROR",
    "SimpleHTTPSClientTestCase.test_no_content_length": "ERROR",
    "SimpleHTTPSClientTestCase.test_options_request": "ERROR",
    "SimpleHTTPSClientTestCase.test_queue_timeout": "ERROR",
    "SimpleHTTPSClientTestCase.test_redirect_connection_limit": "ERROR",
    "SimpleHTTPSClientTestCase.test_request_timeout": "ERROR",
    "SimpleHTTPSClientTestCase.test_see_other_redirect": "ERROR",
    "SimpleHTTPSClientTestCase.test_singleton": "PASSED",
    "SimpleHTTPSClientTestCase.test_ssl_context": "ERROR",
    "SimpleHTTPSClientTestCase.test_ssl_context_handshake_fail": "ERROR",
    "SimpleHTTPSClientTestCase.test_ssl_options": "ERROR",
    "SimpleHTTPSClientTestCase.test_ssl_options_handshake_fail": "ERROR",
    "SimpleHTTPSClientTestCase.test_streaming_follow_redirects": "ERROR",
    "SimpleHTTPSClientTestCase.test_sync_body_producer_chunked": "ERROR",
    "SimpleHTTPSClientTestCase.test_sync_body_producer_content_length": "ERROR"
}
diff --git a/tornado/testing.py b/tornado/testing.py
index b79ba592..86d4b574 100644
--- a/tornado/testing.py
+++ b/tornado/testing.py
@@ -407,7 +407,7 @@ class AsyncHTTPTestCase(AsyncTestCase):
 
     def get_url(self, path):
         """Returns an absolute url for the given path on the test server."""
-        return '%s://localhost:%s%s' % (self.get_protocol(),
+        return '%s://127.0.0.1:%s%s' % (self.get_protocol(),
                                         self.get_http_port(), path)
 
     def tearDown(self):
 

{"tornado/testing.py": "#!/usr/bin/env python\n\"\"\"Support classes for automated testing.\n\n* `AsyncTestCase` and `AsyncHTTPTestCase`:  Subclasses of unittest.TestCase\n  with additional support for testing asynchronous (`.IOLoop`-based) code.\n\n* `ExpectLog`: Make test logs less spammy.\n\n* `main()`: A simple test runner (wrapper around unittest.main()) with support\n  for the tornado.autoreload module to rerun the tests when code changes.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\ntry:\n    from tornado import gen\n    from tornado.httpclient import AsyncHTTPClient\n    from tornado.httpserver import HTTPServer\n    from tornado.simple_httpclient import SimpleAsyncHTTPClient\n    from tornado.ioloop import IOLoop, TimeoutError\n    from tornado import netutil\n    from tornado.process import Subprocess\nexcept ImportError:\n    # These modules are not importable on app engine.  Parts of this module\n    # won't work, but e.g. main() will.\n    AsyncHTTPClient = None  # type: ignore\n    gen = None  # type: ignore\n    HTTPServer = None  # type: ignore\n    IOLoop = None  # type: ignore\n    netutil = None  # type: ignore\n    SimpleAsyncHTTPClient = None  # type: ignore\n    Subprocess = None  # type: ignore\nfrom tornado.log import gen_log, app_log\nfrom tornado.stack_context import ExceptionStackContext\nfrom tornado.util import raise_exc_info, basestring_type, PY3\nimport functools\nimport inspect\nimport logging\nimport os\nimport re\nimport signal\nimport socket\nimport sys\n\nif PY3:\n    from io import StringIO\nelse:\n    from cStringIO import StringIO\n\ntry:\n    from collections.abc import Generator as GeneratorType  # type: ignore\nexcept ImportError:\n    from types import GeneratorType  # type: ignore\n\nif sys.version_info >= (3, 5):\n    iscoroutine = inspect.iscoroutine  # type: ignore\n    iscoroutinefunction = inspect.iscoroutinefunction  # type: ignore\nelse:\n    iscoroutine = iscoroutinefunction = lambda f: False\n\n# Tornado's own test suite requires the updated unittest module\n# (either py27+ or unittest2) so tornado.test.util enforces\n# this requirement, but for other users of tornado.testing we want\n# to allow the older version if unitest2 is not available.\nif PY3:\n    # On python 3, mixing unittest2 and unittest (including doctest)\n    # doesn't seem to work, so always use unittest.\n    import unittest\nelse:\n    # On python 2, prefer unittest2 when available.\n    try:\n        import unittest2 as unittest  # type: ignore\n    except ImportError:\n        import unittest  # type: ignore\n\n\ndef bind_unused_port(reuse_port=False):\n    \"\"\"Binds a server socket to an available port on localhost.\n\n    Returns a tuple (socket, port).\n\n    .. versionchanged:: 4.4\n       Always binds to ``127.0.0.1`` without resolving the name\n       ``localhost``.\n    \"\"\"\n    sock = netutil.bind_sockets(None, '127.0.0.1', family=socket.AF_INET,\n                                reuse_port=reuse_port)[0]\n    port = sock.getsockname()[1]\n    return sock, port\n\n\ndef get_async_test_timeout():\n    \"\"\"Get the global timeout setting for async tests.\n\n    Returns a float, the timeout in seconds.\n\n    .. versionadded:: 3.1\n    \"\"\"\n    try:\n        return float(os.environ.get('ASYNC_TEST_TIMEOUT'))\n    except (ValueError, TypeError):\n        return 5\n\n\nclass _TestMethodWrapper(object):\n    \"\"\"Wraps a test method to raise an error if it returns a value.\n\n    This is mainly used to detect undecorated generators (if a test\n    method yields it must use a decorator to consume the generator),\n    but will also detect other kinds of return values (these are not\n    necessarily errors, but we alert anyway since there is no good\n    reason to return a value from a test).\n    \"\"\"\n    def __init__(self, orig_method):\n        self.orig_method = orig_method\n\n    def __call__(self, *args, **kwargs):\n        result = self.orig_method(*args, **kwargs)\n        if isinstance(result, GeneratorType) or iscoroutine(result):\n            raise TypeError(\"Generator and coroutine test methods should be\"\n                            \" decorated with tornado.testing.gen_test\")\n        elif result is not None:\n            raise ValueError(\"Return value from test method ignored: %r\" %\n                             result)\n\n    def __getattr__(self, name):\n        \"\"\"Proxy all unknown attributes to the original method.\n\n        This is important for some of the decorators in the `unittest`\n        module, such as `unittest.skipIf`.\n        \"\"\"\n        return getattr(self.orig_method, name)\n\n\nclass AsyncTestCase(unittest.TestCase):\n    \"\"\"`~unittest.TestCase` subclass for testing `.IOLoop`-based\n    asynchronous code.\n\n    The unittest framework is synchronous, so the test must be\n    complete by the time the test method returns.  This means that\n    asynchronous code cannot be used in quite the same way as usual.\n    To write test functions that use the same ``yield``-based patterns\n    used with the `tornado.gen` module, decorate your test methods\n    with `tornado.testing.gen_test` instead of\n    `tornado.gen.coroutine`.  This class also provides the `stop()`\n    and `wait()` methods for a more manual style of testing.  The test\n    method itself must call ``self.wait()``, and asynchronous\n    callbacks should call ``self.stop()`` to signal completion.\n\n    By default, a new `.IOLoop` is constructed for each test and is available\n    as ``self.io_loop``.  If the code being tested requires a\n    global `.IOLoop`, subclasses should override `get_new_ioloop` to return it.\n\n    The `.IOLoop`'s ``start`` and ``stop`` methods should not be\n    called directly.  Instead, use `self.stop <stop>` and `self.wait\n    <wait>`.  Arguments passed to ``self.stop`` are returned from\n    ``self.wait``.  It is possible to have multiple ``wait``/``stop``\n    cycles in the same test.\n\n    Example::\n\n        # This test uses coroutine style.\n        class MyTestCase(AsyncTestCase):\n            @tornado.testing.gen_test\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                response = yield client.fetch(\"http://www.tornadoweb.org\")\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses argument passing between self.stop and self.wait.\n        class MyTestCase2(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.stop)\n                response = self.wait()\n                # Test contents of response\n                self.assertIn(\"FriendFeed\", response.body)\n\n        # This test uses an explicit callback-based style.\n        class MyTestCase3(AsyncTestCase):\n            def test_http_fetch(self):\n                client = AsyncHTTPClient()\n                client.fetch(\"http://www.tornadoweb.org/\", self.handle_fetch)\n                self.wait()\n\n            def handle_fetch(self, response):\n                # Test contents of response (failures and exceptions here\n                # will cause self.wait() to throw an exception and end the\n                # test).\n                # Exceptions thrown here are magically propagated to\n                # self.wait() in test_http_fetch() via stack_context.\n                self.assertIn(\"FriendFeed\", response.body)\n                self.stop()\n    \"\"\"\n    def __init__(self, methodName='runTest'):\n        super(AsyncTestCase, self).__init__(methodName)\n        self.__stopped = False\n        self.__running = False\n        self.__failure = None\n        self.__stop_args = None\n        self.__timeout = None\n\n        # It's easy to forget the @gen_test decorator, but if you do\n        # the test will silently be ignored because nothing will consume\n        # the generator.  Replace the test method with a wrapper that will\n        # make sure it's not an undecorated generator.\n        setattr(self, methodName, _TestMethodWrapper(getattr(self, methodName)))\n\n    def setUp(self):\n        super(AsyncTestCase, self).setUp()\n        self.io_loop = self.get_new_ioloop()\n        self.io_loop.make_current()\n\n    def tearDown(self):\n        # Clean up Subprocess, so it can be used again with a new ioloop.\n        Subprocess.uninitialize()\n        self.io_loop.clear_current()\n        # Try to clean up any file descriptors left open in the ioloop.\n        # This avoids leaks, especially when tests are run repeatedly\n        # in the same process with autoreload (because curl does not\n        # set FD_CLOEXEC on its file descriptors)\n        self.io_loop.close(all_fds=True)\n        super(AsyncTestCase, self).tearDown()\n        # In case an exception escaped or the StackContext caught an exception\n        # when there wasn't a wait() to re-raise it, do so here.\n        # This is our last chance to raise an exception in a way that the\n        # unittest machinery understands.\n        self.__rethrow()\n\n    def get_new_ioloop(self):\n        \"\"\"Creates a new `.IOLoop` for this test.  May be overridden in\n        subclasses for tests that require a specific `.IOLoop` (usually\n        the singleton `.IOLoop.instance()`).\n        \"\"\"\n        return IOLoop()\n\n    def _handle_exception(self, typ, value, tb):\n        if self.__failure is None:\n            self.__failure = (typ, value, tb)\n        else:\n            app_log.error(\"multiple unhandled exceptions in test\",\n                          exc_info=(typ, value, tb))\n        self.stop()\n        return True\n\n    def __rethrow(self):\n        if self.__failure is not None:\n            failure = self.__failure\n            self.__failure = None\n            raise_exc_info(failure)\n\n    def run(self, result=None):\n        with ExceptionStackContext(self._handle_exception):\n            super(AsyncTestCase, self).run(result)\n        # As a last resort, if an exception escaped super.run() and wasn't\n        # re-raised in tearDown, raise it here.  This will cause the\n        # unittest run to fail messily, but that's better than silently\n        # ignoring an error.\n        self.__rethrow()\n\n    def stop(self, _arg=None, **kwargs):\n        \"\"\"Stops the `.IOLoop`, causing one pending (or future) call to `wait()`\n        to return.\n\n        Keyword arguments or a single positional argument passed to `stop()` are\n        saved and will be returned by `wait()`.\n        \"\"\"\n        assert _arg is None or not kwargs\n        self.__stop_args = kwargs or _arg\n        if self.__running:\n            self.io_loop.stop()\n            self.__running = False\n        self.__stopped = True\n\n    def wait(self, condition=None, timeout=None):\n        \"\"\"Runs the `.IOLoop` until stop is called or timeout has passed.\n\n        In the event of a timeout, an exception will be thrown. The\n        default timeout is 5 seconds; it may be overridden with a\n        ``timeout`` keyword argument or globally with the\n        ``ASYNC_TEST_TIMEOUT`` environment variable.\n\n        If ``condition`` is not None, the `.IOLoop` will be restarted\n        after `stop()` until ``condition()`` returns true.\n\n        .. versionchanged:: 3.1\n           Added the ``ASYNC_TEST_TIMEOUT`` environment variable.\n        \"\"\"\n        if timeout is None:\n            timeout = get_async_test_timeout()\n\n        if not self.__stopped:\n            if timeout:\n                def timeout_func():\n                    try:\n                        raise self.failureException(\n                            'Async operation timed out after %s seconds' %\n                            timeout)\n                    except Exception:\n                        self.__failure = sys.exc_info()\n                    self.stop()\n                self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func)\n            while True:\n                self.__running = True\n                self.io_loop.start()\n                if (self.__failure is not None or\n                        condition is None or condition()):\n                    break\n            if self.__timeout is not None:\n                self.io_loop.remove_timeout(self.__timeout)\n                self.__timeout = None\n        assert self.__stopped\n        self.__stopped = False\n        self.__rethrow()\n        result = self.__stop_args\n        self.__stop_args = None\n        return result\n\n\nclass AsyncHTTPTestCase(AsyncTestCase):\n    \"\"\"A test case that starts up an HTTP server.\n\n    Subclasses must override `get_app()`, which returns the\n    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.\n    Tests will typically use the provided ``self.http_client`` to fetch\n    URLs from this server.\n\n    Example, assuming the \"Hello, world\" example from the user guide is in\n    ``hello.py``::\n\n        import hello\n\n        class TestHelloApp(AsyncHTTPTestCase):\n            def get_app(self):\n                return hello.make_app()\n\n            def test_homepage(self):\n                response = self.fetch('/')\n                self.assertEqual(response.code, 200)\n                self.assertEqual(response.body, 'Hello, world')\n\n    That call to ``self.fetch()`` is equivalent to ::\n\n        self.http_client.fetch(self.get_url('/'), self.stop)\n        response = self.wait()\n\n    which illustrates how AsyncTestCase can turn an asynchronous operation,\n    like ``http_client.fetch()``, into a synchronous operation. If you need\n    to do other asynchronous operations in tests, you'll probably need to use\n    ``stop()`` and ``wait()`` yourself.\n    \"\"\"\n    def setUp(self):\n        super(AsyncHTTPTestCase, self).setUp()\n        sock, port = bind_unused_port()\n        self.__port = port\n\n        self.http_client = self.get_http_client()\n        self._app = self.get_app()\n        self.http_server = self.get_http_server()\n        self.http_server.add_sockets([sock])\n\n    def get_http_client(self):\n        return AsyncHTTPClient()\n\n    def get_http_server(self):\n        return HTTPServer(self._app, **self.get_httpserver_options())\n\n    def get_app(self):\n        \"\"\"Should be overridden by subclasses to return a\n        `tornado.web.Application` or other `.HTTPServer` callback.\n        \"\"\"\n        raise NotImplementedError()\n\n    def fetch(self, path, **kwargs):\n        \"\"\"Convenience method to synchronously fetch a URL.\n\n        The given path will be appended to the local server's host and\n        port.  Any additional kwargs will be passed directly to\n        `.AsyncHTTPClient.fetch` (and so could be used to pass\n        ``method=\"POST\"``, ``body=\"...\"``, etc).\n\n        If the path begins with http:// or https://, it will be treated as a\n        full URL and will be fetched as-is.\n        \"\"\"\n        if path.lower().startswith(('http://', 'https://')):\n            self.http_client.fetch(path, self.stop, **kwargs)\n        else:\n            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)\n        return self.wait()\n\n    def get_httpserver_options(self):\n        \"\"\"May be overridden by subclasses to return additional\n        keyword arguments for the server.\n        \"\"\"\n        return {}\n\n    def get_http_port(self):\n        \"\"\"Returns the port used by the server.\n\n        A new port is chosen for each test.\n        \"\"\"\n        return self.__port\n\n    def get_protocol(self):\n        return 'http'\n\n    def get_url(self, path):\n        \"\"\"Returns an absolute url for the given path on the test server.\"\"\"\n        return '%s://localhost:%s%s' % (self.get_protocol(),\n                                        self.get_http_port(), path)\n\n    def tearDown(self):\n        self.http_server.stop()\n        self.io_loop.run_sync(self.http_server.close_all_connections,\n                              timeout=get_async_test_timeout())\n        self.http_client.close()\n        super(AsyncHTTPTestCase, self).tearDown()\n\n\nclass AsyncHTTPSTestCase(AsyncHTTPTestCase):\n    \"\"\"A test case that starts an HTTPS server.\n\n    Interface is generally the same as `AsyncHTTPTestCase`.\n    \"\"\"\n    def get_http_client(self):\n        return AsyncHTTPClient(force_instance=True,\n                               defaults=dict(validate_cert=False))\n\n    def get_httpserver_options(self):\n        return dict(ssl_options=self.get_ssl_options())\n\n    def get_ssl_options(self):\n        \"\"\"May be overridden by subclasses to select SSL options.\n\n        By default includes a self-signed testing certificate.\n        \"\"\"\n        # Testing keys were generated with:\n        # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509\n        module_dir = os.path.dirname(__file__)\n        return dict(\n            certfile=os.path.join(module_dir, 'test', 'test.crt'),\n            keyfile=os.path.join(module_dir, 'test', 'test.key'))\n\n    def get_protocol(self):\n        return 'https'\n\n\ndef gen_test(func=None, timeout=None):\n    \"\"\"Testing equivalent of ``@gen.coroutine``, to be applied to test methods.\n\n    ``@gen.coroutine`` cannot be used on tests because the `.IOLoop` is not\n    already running.  ``@gen_test`` should be applied to test methods\n    on subclasses of `AsyncTestCase`.\n\n    Example::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test\n            def test_something(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    By default, ``@gen_test`` times out after 5 seconds. The timeout may be\n    overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable,\n    or for each test with the ``timeout`` keyword argument::\n\n        class MyTest(AsyncHTTPTestCase):\n            @gen_test(timeout=10)\n            def test_something_slow(self):\n                response = yield self.http_client.fetch(self.get_url('/'))\n\n    Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`,\n    `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield\n    self.http_client.fetch(self.get_url())`` as shown above instead.\n\n    .. versionadded:: 3.1\n       The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment\n       variable.\n\n    .. versionchanged:: 4.0\n       The wrapper now passes along ``*args, **kwargs`` so it can be used\n       on functions with arguments.\n\n    \"\"\"\n    if timeout is None:\n        timeout = get_async_test_timeout()\n\n    def wrap(f):\n        # Stack up several decorators to allow us to access the generator\n        # object itself.  In the innermost wrapper, we capture the generator\n        # and save it in an attribute of self.  Next, we run the wrapped\n        # function through @gen.coroutine.  Finally, the coroutine is\n        # wrapped again to make it synchronous with run_sync.\n        #\n        # This is a good case study arguing for either some sort of\n        # extensibility in the gen decorators or cancellation support.\n        @functools.wraps(f)\n        def pre_coroutine(self, *args, **kwargs):\n            result = f(self, *args, **kwargs)\n            if isinstance(result, GeneratorType) or iscoroutine(result):\n                self._test_generator = result\n            else:\n                self._test_generator = None\n            return result\n\n        if iscoroutinefunction(f):\n            coro = pre_coroutine\n        else:\n            coro = gen.coroutine(pre_coroutine)\n\n        @functools.wraps(coro)\n        def post_coroutine(self, *args, **kwargs):\n            try:\n                return self.io_loop.run_sync(\n                    functools.partial(coro, self, *args, **kwargs),\n                    timeout=timeout)\n            except TimeoutError as e:\n                # run_sync raises an error with an unhelpful traceback.\n                # Throw it back into the generator or coroutine so the stack\n                # trace is replaced by the point where the test is stopped.\n                self._test_generator.throw(e)\n                # In case the test contains an overly broad except clause,\n                # we may get back here.  In this case re-raise the original\n                # exception, which is better than nothing.\n                raise\n        return post_coroutine\n\n    if func is not None:\n        # Used like:\n        #     @gen_test\n        #     def f(self):\n        #         pass\n        return wrap(func)\n    else:\n        # Used like @gen_test(timeout=10)\n        return wrap\n\n\n# Without this attribute, nosetests will try to run gen_test as a test\n# anywhere it is imported.\ngen_test.__test__ = False  # type: ignore\n\n\nclass ExpectLog(logging.Filter):\n    \"\"\"Context manager to capture and suppress expected log output.\n\n    Useful to make tests of error conditions less noisy, while still\n    leaving unexpected log entries visible.  *Not thread safe.*\n\n    The attribute ``logged_stack`` is set to true if any exception\n    stack trace was logged.\n\n    Usage::\n\n        with ExpectLog('tornado.application', \"Uncaught exception\"):\n            error_response = self.fetch(\"/some_page\")\n\n    .. versionchanged:: 4.3\n       Added the ``logged_stack`` attribute.\n    \"\"\"\n    def __init__(self, logger, regex, required=True):\n        \"\"\"Constructs an ExpectLog context manager.\n\n        :param logger: Logger object (or name of logger) to watch.  Pass\n            an empty string to watch the root logger.\n        :param regex: Regular expression to match.  Any log entries on\n            the specified logger that match this regex will be suppressed.\n        :param required: If true, an exception will be raised if the end of\n            the ``with`` statement is reached without matching any log entries.\n        \"\"\"\n        if isinstance(logger, basestring_type):\n            logger = logging.getLogger(logger)\n        self.logger = logger\n        self.regex = re.compile(regex)\n        self.required = required\n        self.matched = False\n        self.logged_stack = False\n\n    def filter(self, record):\n        if record.exc_info:\n            self.logged_stack = True\n        message = record.getMessage()\n        if self.regex.match(message):\n            self.matched = True\n            return False\n        return True\n\n    def __enter__(self):\n        self.logger.addFilter(self)\n        return self\n\n    def __exit__(self, typ, value, tb):\n        self.logger.removeFilter(self)\n        if not typ and self.required and not self.matched:\n            raise Exception(\"did not get expected log message\")\n\n\ndef main(**kwargs):\n    \"\"\"A simple test runner.\n\n    This test runner is essentially equivalent to `unittest.main` from\n    the standard library, but adds support for tornado-style option\n    parsing and log formatting. It is *not* necessary to use this\n    `main` function to run tests using `AsyncTestCase`; these tests\n    are self-contained and can run with any test runner.\n\n    The easiest way to run a test is via the command line::\n\n        python -m tornado.testing tornado.test.stack_context_test\n\n    See the standard library unittest module for ways in which tests can\n    be specified.\n\n    Projects with many tests may wish to define a test script like\n    ``tornado/test/runtests.py``.  This script should define a method\n    ``all()`` which returns a test suite and then call\n    `tornado.testing.main()`.  Note that even when a test script is\n    used, the ``all()`` test suite may be overridden by naming a\n    single test on the command line::\n\n        # Runs all tests\n        python -m tornado.test.runtests\n        # Runs one test\n        python -m tornado.test.runtests tornado.test.stack_context_test\n\n    Additional keyword arguments passed through to ``unittest.main()``.\n    For example, use ``tornado.testing.main(verbosity=2)``\n    to show many test details as they are run.\n    See http://docs.python.org/library/unittest.html#unittest.main\n    for full argument list.\n    \"\"\"\n    from tornado.options import define, options, parse_command_line\n\n    define('exception_on_interrupt', type=bool, default=True,\n           help=(\"If true (default), ctrl-c raises a KeyboardInterrupt \"\n                 \"exception.  This prints a stack trace but cannot interrupt \"\n                 \"certain operations.  If false, the process is more reliably \"\n                 \"killed, but does not print a stack trace.\"))\n\n    # support the same options as unittest's command-line interface\n    define('verbose', type=bool)\n    define('quiet', type=bool)\n    define('failfast', type=bool)\n    define('catch', type=bool)\n    define('buffer', type=bool)\n\n    argv = [sys.argv[0]] + parse_command_line(sys.argv)\n\n    if not options.exception_on_interrupt:\n        signal.signal(signal.SIGINT, signal.SIG_DFL)\n\n    if options.verbose is not None:\n        kwargs['verbosity'] = 2\n    if options.quiet is not None:\n        kwargs['verbosity'] = 0\n    if options.failfast is not None:\n        kwargs['failfast'] = True\n    if options.catch is not None:\n        kwargs['catchbreak'] = True\n    if options.buffer is not None:\n        kwargs['buffer'] = True\n\n    if __name__ == '__main__' and len(argv) == 1:\n        print(\"No tests specified\", file=sys.stderr)\n        sys.exit(1)\n    try:\n        # In order to be able to run tests by their fully-qualified name\n        # on the command line without importing all tests here,\n        # module must be set to None.  Python 3.2's unittest.main ignores\n        # defaultTest if no module is given (it tries to do its own\n        # test discovery, which is incompatible with auto2to3), so don't\n        # set module if we're not asking for a specific test.\n        if len(argv) > 1:\n            unittest.main(module=None, argv=argv, **kwargs)\n        else:\n            unittest.main(defaultTest=\"all\", argv=argv, **kwargs)\n    except SystemExit as e:\n        if e.code == 0:\n            gen_log.info('PASS')\n        else:\n            gen_log.error('FAIL')\n        raise\n\n\nif __name__ == '__main__':\n    main()\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Host Header Mismatch Causes Test Failures**

**Description**
When running tests, the host header is set to `'127.0.0.1'` instead of `'localhost'`. This discrepancy causes assertions that expect `'localhost'` to fail.

**Example Buggy Code**
```python
host_re = re.compile(b"^localhost:[0-9]+$")
response = self.fetch("/host_echo")
self.assertTrue(host_re.match(response.body))
```
In this code, the regular expression expects the host to start with `'localhost'`, but the actual response contains `'127.0.0.1'`, leading to a mismatch.

**Expected Behavior**
The host header should match `'localhost'` as specified in the test, ensuring that the regular expression validation passes.

**Actual Behavior**
The host header contains `'127.0.0.1'`, which does not satisfy the regular expression `^localhost:[0-9]+$`, resulting in failed assertions.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/testing.py
#!/usr/bin/env python
"""Support classes for automated testing.

* `AsyncTestCase` and `AsyncHTTPTestCase`:  Subclasses of unittest.TestCase
  with additional support for testing asynchronous (`.IOLoop`-based) code.

* `ExpectLog`: Make test logs less spammy.

* `main()`: A simple test runner (wrapper around unittest.main()) with support
  for the tornado.autoreload module to rerun the tests when code changes.
"""

from __future__ import absolute_import, division, print_function

try:
    from tornado import gen
    from tornado.httpclient import AsyncHTTPClient
    from tornado.httpserver import HTTPServer
    from tornado.simple_httpclient import SimpleAsyncHTTPClient
    from tornado.ioloop import IOLoop, TimeoutError
    from tornado import netutil
    from tornado.process import Subprocess
except ImportError:
    # These modules are not importable on app engine.  Parts of this module
    # won't work, but e.g. main() will.
    AsyncHTTPClient = None  # type: ignore
    gen = None  # type: ignore
    HTTPServer = None  # type: ignore
    IOLoop = None  # type: ignore
    netutil = None  # type: ignore
    SimpleAsyncHTTPClient = None  # type: ignore
    Subprocess = None  # type: ignore
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

if PY3:
    from io import StringIO
else:
    from cStringIO import StringIO

try:
    from collections.abc import Generator as GeneratorType  # type: ignore
except ImportError:
    from types import GeneratorType  # type: ignore

if sys.version_info >= (3, 5):
    iscoroutine = inspect.iscoroutine  # type: ignore
    iscoroutinefunction = inspect.iscoroutinefunction  # type: ignore
else:
    iscoroutine = iscoroutinefunction = lambda f: False

# Tornado's own test suite requires the updated unittest module
# (either py27+ or unittest2) so tornado.test.util enforces
# this requirement, but for other users of tornado.testing we want
# to allow the older version if unitest2 is not available.
if PY3:
    # On python 3, mixing unittest2 and unittest (including doctest)
    # doesn't seem to work, so always use unittest.
    import unittest
else:
    # On python 2, prefer unittest2 when available.
    try:
        import unittest2 as unittest  # type: ignore
    except ImportError:
        import unittest  # type: ignore


def bind_unused_port(reuse_port=False):
    """Binds a server socket to an available port on localhost.

    Returns a tuple (socket, port).

    .. versionchanged:: 4.4
       Always binds to ``127.0.0.1`` without resolving the name
       ``localhost``.
    """
    sock = netutil.bind_sockets(None, '127.0.0.1', family=socket.AF_INET,
                                reuse_port=reuse_port)[0]
    port = sock.getsockname()[1]
    return sock, port


def get_async_test_timeout():
    """Get the global timeout setting for async tests.

    Returns a float, the timeout in seconds.

    .. versionadded:: 3.1
    """
    try:
        return float(os.environ.get('ASYNC_TEST_TIMEOUT'))
    except (ValueError, TypeError):
        return 5


class _TestMethodWrapper(object):
    """Wraps a test method to raise an error if it returns a value.

    This is mainly used to detect undecorated generators (if a test
    method yields it must use a decorator to consume the generator),
    but will also detect other kinds of return values (these are not
    necessarily errors, but we alert anyway since there is no good
    reason to return a value from a test).
    """
    def __init__(self, orig_method):
        self.orig_method = orig_method

    def __call__(self, *args, **kwargs):
        result = self.orig_method(*args, **kwargs)
        if isinstance(result, GeneratorType) or iscoroutine(result):
            raise TypeError("Generator and coroutine test methods should be"
                            " decorated with tornado.testing.gen_test")
        elif result is not None:
            raise ValueError("Return value from test method ignored: %r" %
                             result)

    def __getattr__(self, name):
        """Proxy all unknown attributes to the original method.

        This is important for some of the decorators in the `unittest`
        module, such as `unittest.skipIf`.
        """
        return getattr(self.orig_method, name)


class AsyncTestCase(unittest.TestCase):
    """`~unittest.TestCase` subclass for testing `.IOLoop`-based
    asynchronous code.

    The unittest framework is synchronous, so the test must be
    complete by the time the test method returns.  This means that
    asynchronous code cannot be used in quite the same way as usual.
    To write test functions that use the same ``yield``-based patterns
    used with the `tornado.gen` module, decorate your test methods
    with `tornado.testing.gen_test` instead of
    `tornado.gen.coroutine`.  This class also provides the `stop()`
    and `wait()` methods for a more manual style of testing.  The test
    method itself must call ``self.wait()``, and asynchronous
    callbacks should call ``self.stop()`` to signal completion.

    By default, a new `.IOLoop` is constructed for each test and is available
    as ``self.io_loop``.  If the code being tested requires a
    global `.IOLoop`, subclasses should override `get_new_ioloop` to return it.

    The `.IOLoop`'s ``start`` and ``stop`` methods should not be
    called directly.  Instead, use `self.stop <stop>` and `self.wait
    <wait>`.  Arguments passed to ``self.stop`` are returned from
    ``self.wait``.  It is possible to have multiple ``wait``/``stop``
    cycles in the same test.

    Example::

        # This test uses coroutine style.
        class MyTestCase(AsyncTestCase):
            @tornado.testing.gen_test
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                response = yield client.fetch("http://www.tornadoweb.org")
                # Test contents of response
                self.assertIn("FriendFeed", response.body)

        # This test uses argument passing between self.stop and self.wait.
        class MyTestCase2(AsyncTestCase):
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                client.fetch("http://www.tornadoweb.org/", self.stop)
                response = self.wait()
                # Test contents of response
                self.assertIn("FriendFeed", response.body)

        # This test uses an explicit callback-based style.
        class MyTestCase3(AsyncTestCase):
            def test_http_fetch(self):
                client = AsyncHTTPClient()
                client.fetch("http://www.tornadoweb.org/", self.handle_fetch)
                self.wait()

            def handle_fetch(self, response):
                # Test contents of response (failures and exceptions here
                # will cause self.wait() to throw an exception and end the
                # test).
                # Exceptions thrown here are magically propagated to
                # self.wait() in test_http_fetch() via stack_context.
                self.assertIn("FriendFeed", response.body)
                self.stop()
    """
    def __init__(self, methodName='runTest'):
        super(AsyncTestCase, self).__init__(methodName)
        self.__stopped = False
        self.__running = False
        self.__failure = None
        self.__stop_args = None
        self.__timeout = None

        # It's easy to forget the @gen_test decorator, but if you do
        # the test will silently be ignored because nothing will consume
        # the generator.  Replace the test method with a wrapper that will
        # make sure it's not an undecorated generator.
        setattr(self, methodName, _TestMethodWrapper(getattr(self, methodName)))

    def setUp(self):
        super(AsyncTestCase, self).setUp()
        self.io_loop = self.get_new_ioloop()
        self.io_loop.make_current()

    def tearDown(self):
        # Clean up Subprocess, so it can be used again with a new ioloop.
        Subprocess.uninitialize()
        self.io_loop.clear_current()
        # Try to clean up any file descriptors left open in the ioloop.
        # This avoids leaks, especially when tests are run repeatedly
        # in the same process with autoreload (because curl does not
        # set FD_CLOEXEC on its file descriptors)
        self.io_loop.close(all_fds=True)
        super(AsyncTestCase, self).tearDown()
        # In case an exception escaped or the StackContext caught an exception
        # when there wasn't a wait() to re-raise it, do so here.
        # This is our last chance to raise an exception in a way that the
        # unittest machinery understands.
        self.__rethrow()

    def get_new_ioloop(self):
        """Creates a new `.IOLoop` for this test.  May be overridden in
        subclasses for tests that require a specific `.IOLoop` (usually
        the singleton `.IOLoop.instance()`).
        """
        return IOLoop()

    def _handle_exception(self, typ, value, tb):
        if self.__failure is None:
            self.__failure = (typ, value, tb)
        else:
            app_log.error("multiple unhandled exceptions in test",
                          exc_info=(typ, value, tb))
        self.stop()
        return True

    def __rethrow(self):
        if self.__failure is not None:
            failure = self.__failure
            self.__failure = None
            raise_exc_info(failure)

    def run(self, result=None):
        with ExceptionStackContext(self._handle_exception):
            super(AsyncTestCase, self).run(result)
        # As a last resort, if an exception escaped super.run() and wasn't
        # re-raised in tearDown, raise it here.  This will cause the
        # unittest run to fail messily, but that's better than silently
        # ignoring an error.
        self.__rethrow()

    def stop(self, _arg=None, **kwargs):
        """Stops the `.IOLoop`, causing one pending (or future) call to `wait()`
        to return.

        Keyword arguments or a single positional argument passed to `stop()` are
        saved and will be returned by `wait()`.
        """
        assert _arg is None or not kwargs
        self.__stop_args = kwargs or _arg
        if self.__running:
            self.io_loop.stop()
            self.__running = False
        self.__stopped = True

    def wait(self, condition=None, timeout=None):
        """Runs the `.IOLoop` until stop is called or timeout has passed.

        In the event of a timeout, an exception will be thrown. The
        default timeout is 5 seconds; it may be overridden with a
        ``timeout`` keyword argument or globally with the
        ``ASYNC_TEST_TIMEOUT`` environment variable.

        If ``condition`` is not None, the `.IOLoop` will be restarted
        after `stop()` until ``condition()`` returns true.

        .. versionchanged:: 3.1
           Added the ``ASYNC_TEST_TIMEOUT`` environment variable.
        """
        if timeout is None:
            timeout = get_async_test_timeout()

        if not self.__stopped:
            if timeout:
                def timeout_func():
                    try:
                        raise self.failureException(
                            'Async operation timed out after %s seconds' %
                            timeout)
                    except Exception:
                        self.__failure = sys.exc_info()
                    self.stop()
                self.__timeout = self.io_loop.add_timeout(self.io_loop.time() + timeout, timeout_func)
            while True:
                self.__running = True
                self.io_loop.start()
                if (self.__failure is not None or
                        condition is None or condition()):
                    break
            if self.__timeout is not None:
                self.io_loop.remove_timeout(self.__timeout)
                self.__timeout = None
        assert self.__stopped
        self.__stopped = False
        self.__rethrow()
        result = self.__stop_args
        self.__stop_args = None
        return result


class AsyncHTTPTestCase(AsyncTestCase):
    """A test case that starts up an HTTP server.

    Subclasses must override `get_app()`, which returns the
    `tornado.web.Application` (or other `.HTTPServer` callback) to be tested.
    Tests will typically use the provided ``self.http_client`` to fetch
    URLs from this server.

    Example, assuming the "Hello, world" example from the user guide is in
    ``hello.py``::

        import hello

        class TestHelloApp(AsyncHTTPTestCase):
            def get_app(self):
                return hello.make_app()

            def test_homepage(self):
                response = self.fetch('/')
                self.assertEqual(response.code, 200)
                self.assertEqual(response.body, 'Hello, world')

    That call to ``self.fetch()`` is equivalent to ::

        self.http_client.fetch(self.get_url('/'), self.stop)
        response = self.wait()

    which illustrates how AsyncTestCase can turn an asynchronous operation,
    like ``http_client.fetch()``, into a synchronous operation. If you need
    to do other asynchronous operations in tests, you'll probably need to use
    ``stop()`` and ``wait()`` yourself.
    """
    def setUp(self):
        super(AsyncHTTPTestCase, self).setUp()
        sock, port = bind_unused_port()
        self.__port = port

        self.http_client = self.get_http_client()
        self._app = self.get_app()
        self.http_server = self.get_http_server()
        self.http_server.add_sockets([sock])

    def get_http_client(self):
        return AsyncHTTPClient()

    def get_http_server(self):
        return HTTPServer(self._app, **self.get_httpserver_options())

    def get_app(self):
        """Should be overridden by subclasses to return a
        `tornado.web.Application` or other `.HTTPServer` callback.
        """
        raise NotImplementedError()

    def fetch(self, path, **kwargs):
        """Convenience method to synchronously fetch a URL.

        The given path will be appended to the local server's host and
        port.  Any additional kwargs will be passed directly to
        `.AsyncHTTPClient.fetch` (and so could be used to pass
        ``method="POST"``, ``body="..."``, etc).

        If the path begins with http:// or https://, it will be treated as a
        full URL and will be fetched as-is.
        """
        if path.lower().startswith(('http://', 'https://')):
            self.http_client.fetch(path, self.stop, **kwargs)
        else:
            self.http_client.fetch(self.get_url(path), self.stop, **kwargs)
        return self.wait()

    def get_httpserver_options(self):
        """May be overridden by subclasses to return additional
        keyword arguments for the server.
        """
        return {}

    def get_http_port(self):
        """Returns the port used by the server.

        A new port is chosen for each test.
        """
        return self.__port

    def get_protocol(self):
        return 'http'

    def get_url(self, path):
        """Returns an absolute url for the given path on the test server."""
        return '%s://localhost:%s%s' % (self.get_protocol(),
                                        self.get_http_port(), path)

    def tearDown(self):
        self.http_server.stop()
        self.io_loop.run_sync(self.http_server.close_all_connections,
                              timeout=get_async_test_timeout())
        self.http_client.close()
        super(AsyncHTTPTestCase, self).tearDown()


class AsyncHTTPSTestCase(AsyncHTTPTestCase):
    """A test case that starts an HTTPS server.

    Interface is generally the same as `AsyncHTTPTestCase`.
    """
    def get_http_client(self):
        return AsyncHTTPClient(force_instance=True,
                               defaults=dict(validate_cert=False))

    def get_httpserver_options(self):
        return dict(ssl_options=self.get_ssl_options())

    def get_ssl_options(self):
        """May be overridden by subclasses to select SSL options.

        By default includes a self-signed testing certificate.
        """
        # Testing keys were generated with:
        # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509
        module_dir = os.path.dirname(__file__)
        return dict(
            certfile=os.path.join(module_dir, 'test', 'test.crt'),
            keyfile=os.path.join(module_dir, 'test', 'test.key'))

    def get_protocol(self):
        return 'https'


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 self.http_client.fetch(self.get_url('/'))

    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 self.http_client.fetch(self.get_url('/'))

    Note that ``@gen_test`` is incompatible with `AsyncTestCase.stop`,
    `AsyncTestCase.wait`, and `AsyncHTTPTestCase.fetch`. Use ``yield
    self.http_client.fetch(self.get_url())`` as shown above instead.

    .. 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


# Without this attribute, nosetests will try to run gen_test as a test
# anywhere it is imported.
gen_test.__test__ = False  # type: ignore


class ExpectLog(logging.Filter):
    """Context manager to capture and suppress expected log output.

    Useful to make tests of error conditions less noisy, while still
    leaving unexpected log entries visible.  *Not thread safe.*

    The attribute ``logged_stack`` is set to true if any exception
    stack trace was logged.

    Usage::

        with ExpectLog('tornado.application', "Uncaught exception"):
            error_response = self.fetch("/some_page")

    .. versionchanged:: 4.3
       Added the ``logged_stack`` attribute.
    """
    def __init__(self, logger, regex, required=True):
        """Constructs an ExpectLog context manager.

        :param logger: Logger object (or name of logger) to watch.  Pass
            an empty string to watch the root logger.
        :param regex: Regular expression to match.  Any log entries on
            the specified logger that match this regex will be suppressed.
        :param required: If true, an exception will be raised if the end of
            the ``with`` statement is reached without matching any log entries.
        """
        if isinstance(logger, basestring_type):
            logger = logging.getLogger(logger)
        self.logger = logger
        self.regex = re.compile(regex)
        self.required = required
        self.matched = False
        self.logged_stack = False

    def filter(self, record):
        if record.exc_info:
            self.logged_stack = True
        message = record.getMessage()
        if self.regex.match(message):
            self.matched = True
            return False
        return True

    def __enter__(self):
        self.logger.addFilter(self)
        return self

    def __exit__(self, typ, value, tb):
        self.logger.removeFilter(self)
        if not typ and self.required and not self.matched:
            raise Exception("did not get expected log message")


def main(**kwargs):
    """A simple test runner.

    This test runner is essentially equivalent to `unittest.main` from
    the standard library, but adds support for tornado-style option
    parsing and log formatting. It is *not* necessary to use this
    `main` function to run tests using `AsyncTestCase`; these tests
    are self-contained and can run with any test runner.

    The easiest way to run a test is via the command line::

        python -m tornado.testing tornado.test.stack_context_test

    See the standard library unittest module for ways in which tests can
    be specified.

    Projects with many tests may wish to define a test script like
    ``tornado/test/runtests.py``.  This script should define a method
    ``all()`` which returns a test suite and then call
    `tornado.testing.main()`.  Note that even when a test script is
    used, the ``all()`` test suite may be overridden by naming a
    single test on the command line::

        # Runs all tests
        python -m tornado.test.runtests
        # Runs one test
        python -m tornado.test.runtests tornado.test.stack_context_test

    Additional keyword arguments passed through to ``unittest.main()``.
    For example, use ``tornado.testing.main(verbosity=2)``
    to show many test details as they are run.
    See http://docs.python.org/library/unittest.html#unittest.main
    for full argument list.
    """
    from tornado.options import define, options, parse_command_line

    define('exception_on_interrupt', type=bool, default=True,
           help=("If true (default), ctrl-c raises a KeyboardInterrupt "
                 "exception.  This prints a stack trace but cannot interrupt "
                 "certain operations.  If false, the process is more reliably "
                 "killed, but does not print a stack trace."))

    # support the same options as unittest's command-line interface
    define('verbose', type=bool)
    define('quiet', type=bool)
    define('failfast', type=bool)
    define('catch', type=bool)
    define('buffer', type=bool)

    argv = [sys.argv[0]] + parse_command_line(sys.argv)

    if not options.exception_on_interrupt:
        signal.signal(signal.SIGINT, signal.SIG_DFL)

    if options.verbose is not None:
        kwargs['verbosity'] = 2
    if options.quiet is not None:
        kwargs['verbosity'] = 0
    if options.failfast is not None:
        kwargs['failfast'] = True
    if options.catch is not None:
        kwargs['catchbreak'] = True
    if options.buffer is not None:
        kwargs['buffer'] = True

    if __name__ == '__main__' and len(argv) == 1:
        print("No tests specified", file=sys.stderr)
        sys.exit(1)
    try:
        # In order to be able to run tests by their fully-qualified name
        # on the command line without importing all tests here,
        # module must be set to None.  Python 3.2's unittest.main ignores
        # defaultTest if no module is given (it tries to do its own
        # test discovery, which is incompatible with auto2to3), so don't
        # set module if we're not asking for a specific test.
        if len(argv) > 1:
            unittest.main(module=None, argv=argv, **kwargs)
        else:
            unittest.main(defaultTest="all", argv=argv, **kwargs)
    except SystemExit as e:
        if e.code == 0:
            gen_log.info('PASS')
        else:
            gen_log.error('FAIL')
        raise


if __name__ == '__main__':
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user