{
    "file_diffs": [
        {
            "old_file_content": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"HTTP utility code shared by clients and servers.\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport datetime\nimport numbers\nimport re\nimport time\n\nfrom tornado.escape import native_str, parse_qs_bytes, utf8\nfrom tornado.log import gen_log\nfrom tornado.util import ObjectDict\n\ntry:\n    from httplib import responses  # py2\nexcept ImportError:\n    from http.client import responses  # py3\n\n# responses is unused in this file, but we re-export it to other files.\n# Reference it so pyflakes doesn't complain.\nresponses\n\ntry:\n    from urllib import urlencode  # py2\nexcept ImportError:\n    from urllib.parse import urlencode  # py3\n\n\nclass HTTPHeaders(dict):\n    \"\"\"A dictionary that maintains Http-Header-Case for all keys.\n\n    Supports multiple values per key via a pair of new methods,\n    add() and get_list().  The regular dictionary interface returns a single\n    value per key, with multiple values joined by a comma.\n\n    >>> h = HTTPHeaders({\"content-type\": \"text/html\"})\n    >>> list(h.keys())\n    ['Content-Type']\n    >>> h[\"Content-Type\"]\n    'text/html'\n\n    >>> h.add(\"Set-Cookie\", \"A=B\")\n    >>> h.add(\"Set-Cookie\", \"C=D\")\n    >>> h[\"set-cookie\"]\n    'A=B,C=D'\n    >>> h.get_list(\"set-cookie\")\n    ['A=B', 'C=D']\n\n    >>> for (k,v) in sorted(h.get_all()):\n    ...    print('%s: %s' % (k,v))\n    ...\n    Content-Type: text/html\n    Set-Cookie: A=B\n    Set-Cookie: C=D\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        # Don't pass args or kwargs to dict.__init__, as it will bypass\n        # our __setitem__\n        dict.__init__(self)\n        self._as_list = {}\n        self._last_key = None\n        if (len(args) == 1 and len(kwargs) == 0 and\n                isinstance(args[0], HTTPHeaders)):\n            # Copy constructor\n            for k, v in args[0].get_all():\n                self.add(k, v)\n        else:\n            # Dict-style initialization\n            self.update(*args, **kwargs)\n\n    # new public methods\n\n    def add(self, name, value):\n        \"\"\"Adds a new value for the given key.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        self._last_key = norm_name\n        if norm_name in self:\n            # bypass our override of __setitem__ since it modifies _as_list\n            dict.__setitem__(self, norm_name,\n                             native_str(self[norm_name]) + ',' +\n                             native_str(value))\n            self._as_list[norm_name].append(value)\n        else:\n            self[norm_name] = value\n\n    def get_list(self, name):\n        \"\"\"Returns all values for the given header as a list.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        return self._as_list.get(norm_name, [])\n\n    def get_all(self):\n        \"\"\"Returns an iterable of all (name, value) pairs.\n\n        If a header has multiple values, multiple pairs will be\n        returned with the same name.\n        \"\"\"\n        for name, values in self._as_list.items():\n            for value in values:\n                yield (name, value)\n\n    def parse_line(self, line):\n        \"\"\"Updates the dictionary with a single header line.\n\n        >>> h = HTTPHeaders()\n        >>> h.parse_line(\"Content-Type: text/html\")\n        >>> h.get('content-type')\n        'text/html'\n        \"\"\"\n        if line[0].isspace():\n            # continuation of a multi-line header\n            new_part = ' ' + line.lstrip()\n            self._as_list[self._last_key][-1] += new_part\n            dict.__setitem__(self, self._last_key,\n                             self[self._last_key] + new_part)\n        else:\n            name, value = line.split(\":\", 1)\n            self.add(name, value.strip())\n\n    @classmethod\n    def parse(cls, headers):\n        \"\"\"Returns a dictionary from HTTP header text.\n\n        >>> h = HTTPHeaders.parse(\"Content-Type: text/html\\\\r\\\\nContent-Length: 42\\\\r\\\\n\")\n        >>> sorted(h.items())\n        [('Content-Length', '42'), ('Content-Type', 'text/html')]\n        \"\"\"\n        h = cls()\n        for line in headers.splitlines():\n            if line:\n                h.parse_line(line)\n        return h\n\n    # dict implementation overrides\n\n    def __setitem__(self, name, value):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__setitem__(self, norm_name, value)\n        self._as_list[norm_name] = [value]\n\n    def __getitem__(self, name):\n        return dict.__getitem__(self, HTTPHeaders._normalize_name(name))\n\n    def __delitem__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__delitem__(self, norm_name)\n        del self._as_list[norm_name]\n\n    def __contains__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        return dict.__contains__(self, norm_name)\n\n    def get(self, name, default=None):\n        return dict.get(self, HTTPHeaders._normalize_name(name), default)\n\n    def update(self, *args, **kwargs):\n        # dict.update bypasses our __setitem__\n        for k, v in dict(*args, **kwargs).items():\n            self[k] = v\n\n    def copy(self):\n        # default implementation returns dict(self), not the subclass\n        return HTTPHeaders(self)\n\n    _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')\n    _normalized_headers = {}\n\n    @staticmethod\n    def _normalize_name(name):\n        \"\"\"Converts a name to Http-Header-Case.\n\n        >>> HTTPHeaders._normalize_name(\"coNtent-TYPE\")\n        'Content-Type'\n        \"\"\"\n        try:\n            return HTTPHeaders._normalized_headers[name]\n        except KeyError:\n            if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):\n                normalized = name\n            else:\n                normalized = \"-\".join([w.capitalize() for w in name.split(\"-\")])\n            HTTPHeaders._normalized_headers[name] = normalized\n            return normalized\n\n\ndef url_concat(url, args):\n    \"\"\"Concatenate url and argument dictionary regardless of whether\n    url has existing query parameters.\n\n    >>> url_concat(\"http://example.com/foo?a=b\", dict(c=\"d\"))\n    'http://example.com/foo?a=b&c=d'\n    \"\"\"\n    if not args:\n        return url\n    if url[-1] not in ('?', '&'):\n        url += '&' if ('?' in url) else '?'\n    return url + urlencode(args)\n\n\nclass HTTPFile(ObjectDict):\n    \"\"\"Represents an HTTP file. For backwards compatibility, its instance\n    attributes are also accessible as dictionary keys.\n\n    :ivar filename:\n    :ivar body:\n    :ivar content_type: The content_type comes from the provided HTTP header\n        and should not be trusted outright given that it can be easily forged.\n    \"\"\"\n    pass\n\n\ndef parse_body_arguments(content_type, body, arguments, files):\n    \"\"\"Parses a form request body.\n\n    Supports \"application/x-www-form-urlencoded\" and \"multipart/form-data\".\n    The content_type parameter should be a string and body should be\n    a byte string.  The arguments and files parameters are dictionaries\n    that will be updated with the parsed contents.\n    \"\"\"\n    if content_type.startswith(\"application/x-www-form-urlencoded\"):\n        uri_arguments = parse_qs_bytes(native_str(body))\n        for name, values in uri_arguments.items():\n            values = [v for v in values if v]\n            if values:\n                arguments.setdefault(name, []).extend(values)\n    elif content_type.startswith(\"multipart/form-data\"):\n        fields = content_type.split(\";\")\n        for field in fields:\n            k, sep, v = field.strip().partition(\"=\")\n            if k == \"boundary\" and v:\n                parse_multipart_form_data(utf8(v), body, arguments, files)\n                break\n        else:\n            gen_log.warning(\"Invalid multipart/form-data\")\n\n\ndef parse_multipart_form_data(boundary, data, arguments, files):\n    \"\"\"Parses a multipart/form-data body.\n\n    The boundary and data parameters are both byte strings.\n    The dictionaries given in the arguments and files parameters\n    will be updated with the contents of the body.\n    \"\"\"\n    # The standard allows for the boundary to be quoted in the header,\n    # although it's rare (it happens at least for google app engine\n    # xmpp).  I think we're also supposed to handle backslash-escapes\n    # here but I'll save that until we see a client that uses them\n    # in the wild.\n    if boundary.startswith(b'\"') and boundary.endswith(b'\"'):\n        boundary = boundary[1:-1]\n    final_boundary_index = data.rfind(b\"--\" + boundary + b\"--\")\n    if final_boundary_index == -1:\n        gen_log.warning(\"Invalid multipart/form-data: no final boundary\")\n        return\n    parts = data[:final_boundary_index].split(b\"--\" + boundary + b\"\\r\\n\")\n    for part in parts:\n        if not part:\n            continue\n        eoh = part.find(b\"\\r\\n\\r\\n\")\n        if eoh == -1:\n            gen_log.warning(\"multipart/form-data missing headers\")\n            continue\n        headers = HTTPHeaders.parse(part[:eoh].decode(\"utf-8\"))\n        disp_header = headers.get(\"Content-Disposition\", \"\")\n        disposition, disp_params = _parse_header(disp_header)\n        if disposition != \"form-data\" or not part.endswith(b\"\\r\\n\"):\n            gen_log.warning(\"Invalid multipart/form-data\")\n            continue\n        value = part[eoh + 4:-2]\n        if not disp_params.get(\"name\"):\n            gen_log.warning(\"multipart/form-data value missing name\")\n            continue\n        name = disp_params[\"name\"]\n        if disp_params.get(\"filename\"):\n            ctype = headers.get(\"Content-Type\", \"application/unknown\")\n            files.setdefault(name, []).append(HTTPFile(\n                filename=disp_params[\"filename\"], body=value,\n                content_type=ctype))\n        else:\n            arguments.setdefault(name, []).append(value)\n\n\ndef format_timestamp(ts):\n    \"\"\"Formats a timestamp in the format used by HTTP.\n\n    The argument may be a numeric timestamp as returned by `time.time()`,\n    a time tuple as returned by `time.gmtime()`, or a `datetime.datetime`\n    object.\n\n    >>> format_timestamp(1359312200)\n    'Sun, 27 Jan 2013 18:43:20 GMT'\n    \"\"\"\n    if isinstance(ts, (tuple, time.struct_time)):\n        pass\n    elif isinstance(ts, datetime.datetime):\n        ts = ts.utctimetuple()\n    elif isinstance(ts, numbers.Real):\n        ts = time.gmtime(ts)\n    else:\n        raise TypeError(\"unknown timestamp type: %r\" % ts)\n    return time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", ts)\n\n# _parseparam and _parse_header are copied and modified from python2.7's cgi.py\n# The original 2.7 version of this code did not correctly support some\n# combinations of semicolons and double quotes.\n\n\ndef _parseparam(s):\n    while s[:1] == ';':\n        s = s[1:]\n        end = s.find(';')\n        while end > 0 and (s.count('\"', 0, end) - s.count('\\\\\"', 0, end)) % 2:\n            end = s.find(';', end + 1)\n        if end < 0:\n            end = len(s)\n        f = s[:end]\n        yield f.strip()\n        s = s[end:]\n\n\ndef _parse_header(line):\n    \"\"\"Parse a Content-type like header.\n\n    Return the main content-type and a dictionary of options.\n\n    \"\"\"\n    parts = _parseparam(';' + line)\n    key = next(parts)\n    pdict = {}\n    for p in parts:\n        i = p.find('=')\n        if i >= 0:\n            name = p[:i].strip().lower()\n            value = p[i + 1:].strip()\n            if len(value) >= 2 and value[0] == value[-1] == '\"':\n                value = value[1:-1]\n                value = value.replace('\\\\\\\\', '\\\\').replace('\\\\\"', '\"')\n            pdict[name] = value\n    return key, pdict\n\n\ndef doctests():\n    import doctest\n    return doctest.DocTestSuite()\n",
            "new_file_content": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"HTTP utility code shared by clients and servers.\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport datetime\nimport numbers\nimport re\nimport time\n\nfrom tornado.escape import native_str, parse_qs_bytes, utf8\nfrom tornado.log import gen_log\nfrom tornado.util import ObjectDict\n\ntry:\n    from httplib import responses  # py2\nexcept ImportError:\n    from http.client import responses  # py3\n\n# responses is unused in this file, but we re-export it to other files.\n# Reference it so pyflakes doesn't complain.\nresponses\n\ntry:\n    from urllib import urlencode  # py2\nexcept ImportError:\n    from urllib.parse import urlencode  # py3\n\n\nclass HTTPHeaders(dict):\n    \"\"\"A dictionary that maintains Http-Header-Case for all keys.\n\n    Supports multiple values per key via a pair of new methods,\n    add() and get_list().  The regular dictionary interface returns a single\n    value per key, with multiple values joined by a comma.\n\n    >>> h = HTTPHeaders({\"content-type\": \"text/html\"})\n    >>> list(h.keys())\n    ['Content-Type']\n    >>> h[\"Content-Type\"]\n    'text/html'\n\n    >>> h.add(\"Set-Cookie\", \"A=B\")\n    >>> h.add(\"Set-Cookie\", \"C=D\")\n    >>> h[\"set-cookie\"]\n    'A=B,C=D'\n    >>> h.get_list(\"set-cookie\")\n    ['A=B', 'C=D']\n\n    >>> for (k,v) in sorted(h.get_all()):\n    ...    print('%s: %s' % (k,v))\n    ...\n    Content-Type: text/html\n    Set-Cookie: A=B\n    Set-Cookie: C=D\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        # Don't pass args or kwargs to dict.__init__, as it will bypass\n        # our __setitem__\n        dict.__init__(self)\n        self._as_list = {}\n        self._last_key = None\n        if (len(args) == 1 and len(kwargs) == 0 and\n                isinstance(args[0], HTTPHeaders)):\n            # Copy constructor\n            for k, v in args[0].get_all():\n                self.add(k, v)\n        else:\n            # Dict-style initialization\n            self.update(*args, **kwargs)\n\n    # new public methods\n\n    def add(self, name, value):\n        \"\"\"Adds a new value for the given key.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        self._last_key = norm_name\n        if norm_name in self:\n            # bypass our override of __setitem__ since it modifies _as_list\n            dict.__setitem__(self, norm_name,\n                             native_str(self[norm_name]) + ',' +\n                             native_str(value))\n            self._as_list[norm_name].append(value)\n        else:\n            self[norm_name] = value\n\n    def get_list(self, name):\n        \"\"\"Returns all values for the given header as a list.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        return self._as_list.get(norm_name, [])\n\n    def get_all(self):\n        \"\"\"Returns an iterable of all (name, value) pairs.\n\n        If a header has multiple values, multiple pairs will be\n        returned with the same name.\n        \"\"\"\n        for name, values in self._as_list.items():\n            for value in values:\n                yield (name, value)\n\n    def parse_line(self, line):\n        \"\"\"Updates the dictionary with a single header line.\n\n        >>> h = HTTPHeaders()\n        >>> h.parse_line(\"Content-Type: text/html\")\n        >>> h.get('content-type')\n        'text/html'\n        \"\"\"\n        if line[0].isspace():\n            # continuation of a multi-line header\n            new_part = ' ' + line.lstrip()\n            self._as_list[self._last_key][-1] += new_part\n            dict.__setitem__(self, self._last_key,\n                             self[self._last_key] + new_part)\n        else:\n            name, value = line.split(\":\", 1)\n            self.add(name, value.strip())\n\n    @classmethod\n    def parse(cls, headers):\n        \"\"\"Returns a dictionary from HTTP header text.\n\n        >>> h = HTTPHeaders.parse(\"Content-Type: text/html\\\\r\\\\nContent-Length: 42\\\\r\\\\n\")\n        >>> sorted(h.items())\n        [('Content-Length', '42'), ('Content-Type', 'text/html')]\n        \"\"\"\n        h = cls()\n        for line in headers.splitlines():\n            if line:\n                h.parse_line(line)\n        return h\n\n    # dict implementation overrides\n\n    def __setitem__(self, name, value):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__setitem__(self, norm_name, value)\n        self._as_list[norm_name] = [value]\n\n    def __getitem__(self, name):\n        return dict.__getitem__(self, HTTPHeaders._normalize_name(name))\n\n    def __delitem__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__delitem__(self, norm_name)\n        del self._as_list[norm_name]\n\n    def __contains__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        return dict.__contains__(self, norm_name)\n\n    def get(self, name, default=None):\n        return dict.get(self, HTTPHeaders._normalize_name(name), default)\n\n    def update(self, *args, **kwargs):\n        # dict.update bypasses our __setitem__\n        for k, v in dict(*args, **kwargs).items():\n            self[k] = v\n\n    def copy(self):\n        # default implementation returns dict(self), not the subclass\n        return HTTPHeaders(self)\n\n    _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')\n    _normalized_headers = {}\n\n    @staticmethod\n    def _normalize_name(name):\n        \"\"\"Converts a name to Http-Header-Case.\n\n        >>> HTTPHeaders._normalize_name(\"coNtent-TYPE\")\n        'Content-Type'\n        \"\"\"\n        try:\n            return HTTPHeaders._normalized_headers[name]\n        except KeyError:\n            if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):\n                normalized = name\n            else:\n                normalized = \"-\".join([w.capitalize() for w in name.split(\"-\")])\n            HTTPHeaders._normalized_headers[name] = normalized\n            return normalized\n\n\ndef url_concat(url, args):\n    \"\"\"Concatenate url and argument dictionary regardless of whether\n    url has existing query parameters.\n\n    >>> url_concat(\"http://example.com/foo?a=b\", dict(c=\"d\"))\n    'http://example.com/foo?a=b&c=d'\n    \"\"\"\n    if not args:\n        return url\n    if url[-1] not in ('?', '&'):\n        url += '&' if ('?' in url) else '?'\n    return url + urlencode(args)\n\n\nclass HTTPFile(ObjectDict):\n    \"\"\"Represents an HTTP file. For backwards compatibility, its instance\n    attributes are also accessible as dictionary keys.\n\n    :ivar filename:\n    :ivar body:\n    :ivar content_type: The content_type comes from the provided HTTP header\n        and should not be trusted outright given that it can be easily forged.\n    \"\"\"\n    pass\n\n\ndef parse_body_arguments(content_type, body, arguments, files):\n    \"\"\"Parses a form request body.\n\n    Supports \"application/x-www-form-urlencoded\" and \"multipart/form-data\".\n    The content_type parameter should be a string and body should be\n    a byte string.  The arguments and files parameters are dictionaries\n    that will be updated with the parsed contents.\n    \"\"\"\n    if content_type.startswith(\"application/x-www-form-urlencoded\"):\n        uri_arguments = parse_qs_bytes(native_str(body))\n        for name, values in uri_arguments.items():\n            values = [v for v in values if v]\n        uri_arguments = parse_qs_bytes(native_str(body), keep_blank_values=True)\n        for name, values in uri_arguments.items():\n            if values:\n                arguments.setdefault(name, []).extend(values)\n    elif content_type.startswith(\"multipart/form-data\"):\n        fields = content_type.split(\";\")\n        for field in fields:\n            k, sep, v = field.strip().partition(\"=\")\n            if k == \"boundary\" and v:\n                parse_multipart_form_data(utf8(v), body, arguments, files)\n                break\n        else:\n            gen_log.warning(\"Invalid multipart/form-data\")\n\n\ndef parse_multipart_form_data(boundary, data, arguments, files):\n    \"\"\"Parses a multipart/form-data body.\n\n    The boundary and data parameters are both byte strings.\n    The dictionaries given in the arguments and files parameters\n    will be updated with the contents of the body.\n    \"\"\"\n    # The standard allows for the boundary to be quoted in the header,\n    # although it's rare (it happens at least for google app engine\n    # xmpp).  I think we're also supposed to handle backslash-escapes\n    # here but I'll save that until we see a client that uses them\n    # in the wild.\n    if boundary.startswith(b'\"') and boundary.endswith(b'\"'):\n        boundary = boundary[1:-1]\n    final_boundary_index = data.rfind(b\"--\" + boundary + b\"--\")\n    if final_boundary_index == -1:\n        gen_log.warning(\"Invalid multipart/form-data: no final boundary\")\n        return\n    parts = data[:final_boundary_index].split(b\"--\" + boundary + b\"\\r\\n\")\n    for part in parts:\n        if not part:\n            continue\n        eoh = part.find(b\"\\r\\n\\r\\n\")\n        if eoh == -1:\n            gen_log.warning(\"multipart/form-data missing headers\")\n            continue\n        headers = HTTPHeaders.parse(part[:eoh].decode(\"utf-8\"))\n        disp_header = headers.get(\"Content-Disposition\", \"\")\n        disposition, disp_params = _parse_header(disp_header)\n        if disposition != \"form-data\" or not part.endswith(b\"\\r\\n\"):\n            gen_log.warning(\"Invalid multipart/form-data\")\n            continue\n        value = part[eoh + 4:-2]\n        if not disp_params.get(\"name\"):\n            gen_log.warning(\"multipart/form-data value missing name\")\n            continue\n        name = disp_params[\"name\"]\n        if disp_params.get(\"filename\"):\n            ctype = headers.get(\"Content-Type\", \"application/unknown\")\n            files.setdefault(name, []).append(HTTPFile(\n                filename=disp_params[\"filename\"], body=value,\n                content_type=ctype))\n        else:\n            arguments.setdefault(name, []).append(value)\n\n\ndef format_timestamp(ts):\n    \"\"\"Formats a timestamp in the format used by HTTP.\n\n    The argument may be a numeric timestamp as returned by `time.time()`,\n    a time tuple as returned by `time.gmtime()`, or a `datetime.datetime`\n    object.\n\n    >>> format_timestamp(1359312200)\n    'Sun, 27 Jan 2013 18:43:20 GMT'\n    \"\"\"\n    if isinstance(ts, (tuple, time.struct_time)):\n        pass\n    elif isinstance(ts, datetime.datetime):\n        ts = ts.utctimetuple()\n    elif isinstance(ts, numbers.Real):\n        ts = time.gmtime(ts)\n    else:\n        raise TypeError(\"unknown timestamp type: %r\" % ts)\n    return time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", ts)\n\n# _parseparam and _parse_header are copied and modified from python2.7's cgi.py\n# The original 2.7 version of this code did not correctly support some\n# combinations of semicolons and double quotes.\n\n\ndef _parseparam(s):\n    while s[:1] == ';':\n        s = s[1:]\n        end = s.find(';')\n        while end > 0 and (s.count('\"', 0, end) - s.count('\\\\\"', 0, end)) % 2:\n            end = s.find(';', end + 1)\n        if end < 0:\n            end = len(s)\n        f = s[:end]\n        yield f.strip()\n        s = s[end:]\n\n\ndef _parse_header(line):\n    \"\"\"Parse a Content-type like header.\n\n    Return the main content-type and a dictionary of options.\n\n    \"\"\"\n    parts = _parseparam(';' + line)\n    key = next(parts)\n    pdict = {}\n    for p in parts:\n        i = p.find('=')\n        if i >= 0:\n            name = p[:i].strip().lower()\n            value = p[i + 1:].strip()\n            if len(value) >= 2 and value[0] == value[-1] == '\"':\n                value = value[1:-1]\n                value = value.replace('\\\\\\\\', '\\\\').replace('\\\\\"', '\"')\n            pdict[name] = value\n    return key, pdict\n\n\ndef doctests():\n    import doctest\n    return doctest.DocTestSuite()\n",
            "header": {
                "file": {
                    "path": "tornado/httputil.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "b9cd1065",
                "new_commit_hash": "f68c7414",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/httputil.py"
            },
            "plus_file": {
                "path": "b/tornado/httputil.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 236,
                            "length": 6
                        },
                        "new_range": {
                            "start": 236,
                            "length": 8
                        },
                        "section": "def parse_body_arguments(content_type, body, arguments, files):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        uri_arguments = parse_qs_bytes(native_str(body))",
                                "type": "context"
                            },
                            {
                                "content": "        for name, values in uri_arguments.items():",
                                "type": "context"
                            },
                            {
                                "content": "            values = [v for v in values if v]",
                                "type": "context"
                            },
                            {
                                "content": "        uri_arguments = parse_qs_bytes(native_str(body), keep_blank_values=True)",
                                "type": "added"
                            },
                            {
                                "content": "        for name, values in uri_arguments.items():",
                                "type": "added"
                            },
                            {
                                "content": "            if values:",
                                "type": "context"
                            },
                            {
                                "content": "                arguments.setdefault(name, []).extend(values)",
                                "type": "context"
                            },
                            {
                                "content": "    elif content_type.startswith(\"multipart/form-data\"):",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/httputil.py",
                            "type": "function",
                            "name": "parse_body_arguments",
                            "content": "def parse_body_arguments(content_type, body, arguments, files):\n    \"\"\"Parses a form request body.\n\n    Supports \"application/x-www-form-urlencoded\" and \"multipart/form-data\".\n    The content_type parameter should be a string and body should be\n    a byte string.  The arguments and files parameters are dictionaries\n    that will be updated with the parsed contents.\n    \"\"\"\n    if content_type.startswith(\"application/x-www-form-urlencoded\"):\n        uri_arguments = parse_qs_bytes(native_str(body))\n        for name, values in uri_arguments.items():\n            values = [v for v in values if v]\n        uri_arguments = parse_qs_bytes(native_str(body), keep_blank_values=True)\n        for name, values in uri_arguments.items():\n            if values:\n                arguments.setdefault(name, []).extend(values)\n    elif content_type.startswith(\"multipart/form-data\"):\n        fields = content_type.split(\";\")\n        for field in fields:\n            k, sep, v = field.strip().partition(\"=\")\n            if k == \"boundary\" and v:\n                parse_multipart_form_data(utf8(v), body, arguments, files)\n                break\n        else:\n            gen_log.warning(\"Invalid multipart/form-data\")",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 227,
                            "end_lineno": 251,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import httpclient, simple_httpclient, netutil\nfrom tornado.escape import json_decode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context, Resolver\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.util import u, bytes_type\nfrom tornado.web import Application, RequestHandler, asynchronous\nimport datetime\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\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\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            self.http_client.fetch(self.get_url(\"/\").replace('https:', 'http:'),\n                                   self.stop,\n                                   request_timeout=3600,\n                                   connect_timeout=3600)\n            response = self.wait()\n        self.assertEqual(response.code, 599)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": \"/__mising__.crt\",\n                          })\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": existing_certificate,\n                          \"keyfile\": \"/__missing__.key\"\n                          })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_certificate\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\nclass RawRequestHTTPConnection(simple_httpclient._HTTPConnection):\n    def set_request(self, request):\n        self.__next_request = request\n\n    def _on_connect(self):\n        self.stream.write(self.__next_request)\n        self.__next_request = None\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self._on_headers)\n\n# This test is also called from wsgi_test\n\n\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body):\n        client = SimpleAsyncHTTPClient(self.io_loop)\n        conn = RawRequestHTTPConnection(\n            self.io_loop, client,\n            httpclient._RequestProxy(\n                httpclient.HTTPRequest(self.get_url(\"/\")),\n                dict(httpclient.HTTPRequest._DEFAULTS)),\n            None, self.stop,\n            1024 * 1024, Resolver(io_loop=self.io_loop))\n        conn.set_request(\n            b\"\\r\\n\".join(headers +\n                         [utf8(\"Content-Length: %d\\r\\n\" % len(body))]) +\n            b\"\\r\\n\" + body)\n        response = self.wait()\n        client.close()\n        response.rethrow()\n        return response\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n            b\"Content-Disposition: form-data; name=argument\",\n            b\"\",\n            u(\"\\u00e1\").encode(\"utf-8\"),\n            b\"--1234567890\",\n            u('Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"').encode(\"utf8\"),\n            b\"\",\n            u(\"\\u00fa\").encode(\"utf-8\"),\n            b\"--1234567890--\",\n            b\"\",\n            ]))\n        data = json_decode(response.body)\n        self.assertEqual(u(\"\\u00e9\"), data[\"header\"])\n        self.assertEqual(u(\"\\u00e1\"), data[\"argument\"])\n        self.assertEqual(u(\"\\u00f3\"), data[\"filename\"])\n        self.assertEqual(u(\"\\u00fa\"), data[\"filebody\"])\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"localhost\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes_type)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes_type)\n        self.write(self.errors)\n\n    def get(self):\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 HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n\n    def tearDown(self):\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        server = HTTPServer(app, io_loop=self.io_loop)\n        server.add_socket(sock)\n        stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        stream.connect(sockfile, self.stop)\n        self.wait()\n        stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.0 200 OK\\r\\n\")\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n        stream.close()\n        server.stop()\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(self.http_version + b' 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        headers = self.read_headers()\n        self.stream.read_bytes(int(headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\n",
            "new_file_content": "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import httpclient, simple_httpclient, netutil\nfrom tornado.escape import json_decode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context, Resolver\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.util import u, bytes_type\nfrom tornado.web import Application, RequestHandler, asynchronous\nimport datetime\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\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\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            self.http_client.fetch(self.get_url(\"/\").replace('https:', 'http:'),\n                                   self.stop,\n                                   request_timeout=3600,\n                                   connect_timeout=3600)\n            response = self.wait()\n        self.assertEqual(response.code, 599)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": \"/__mising__.crt\",\n                          })\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": existing_certificate,\n                          \"keyfile\": \"/__missing__.key\"\n                          })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_certificate\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\nclass RawRequestHTTPConnection(simple_httpclient._HTTPConnection):\n    def set_request(self, request):\n        self.__next_request = request\n\n    def _on_connect(self):\n        self.stream.write(self.__next_request)\n        self.__next_request = None\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self._on_headers)\n\n# This test is also called from wsgi_test\n\n\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body):\n        client = SimpleAsyncHTTPClient(self.io_loop)\n        conn = RawRequestHTTPConnection(\n            self.io_loop, client,\n            httpclient._RequestProxy(\n                httpclient.HTTPRequest(self.get_url(\"/\")),\n                dict(httpclient.HTTPRequest._DEFAULTS)),\n            None, self.stop,\n            1024 * 1024, Resolver(io_loop=self.io_loop))\n        conn.set_request(\n            b\"\\r\\n\".join(headers +\n                         [utf8(\"Content-Length: %d\\r\\n\" % len(body))]) +\n            b\"\\r\\n\" + body)\n        response = self.wait()\n        client.close()\n        response.rethrow()\n        return response\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n            b\"Content-Disposition: form-data; name=argument\",\n            b\"\",\n            u(\"\\u00e1\").encode(\"utf-8\"),\n            b\"--1234567890\",\n            u('Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"').encode(\"utf8\"),\n            b\"\",\n            u(\"\\u00fa\").encode(\"utf-8\"),\n            b\"--1234567890--\",\n            b\"\",\n            ]))\n        data = json_decode(response.body)\n        self.assertEqual(u(\"\\u00e9\"), data[\"header\"])\n        self.assertEqual(u(\"\\u00e1\"), data[\"argument\"])\n        self.assertEqual(u(\"\\u00f3\"), data[\"filename\"])\n        self.assertEqual(u(\"\\u00fa\"), data[\"filebody\"])\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"localhost\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes_type)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes_type)\n        self.write(self.errors)\n\n    def get(self):\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 HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n\n    def tearDown(self):\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        server = HTTPServer(app, io_loop=self.io_loop)\n        server.add_socket(sock)\n        stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        stream.connect(sockfile, self.stop)\n        self.wait()\n        stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.0 200 OK\\r\\n\")\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n        stream.close()\n        server.stop()\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(self.http_version + b' 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        headers = self.read_headers()\n        self.stream.read_bytes(int(headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\n",
            "header": {
                "file": {
                    "path": "tornado/test/httpserver_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "123ae2e7",
                "new_commit_hash": "54b38b46",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/httpserver_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/httpserver_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 258,
                            "length": 6
                        },
                        "new_range": {
                            "start": 258,
                            "length": 8
                        },
                        "section": "class EchoHandler(RequestHandler):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    def get(self):",
                                "type": "context"
                            },
                            {
                                "content": "        self.write(recursive_unicode(self.request.arguments))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def post(self):",
                                "type": "added"
                            },
                            {
                                "content": "        self.write(recursive_unicode(self.request.arguments))",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "class TypeCheckHandler(RequestHandler):",
                                "type": "context"
                            },
                            {
                                "content": "    def prepare(self):",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "class",
                            "name": "EchoHandler",
                            "content": "class EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 257,
                            "end_lineno": 262,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "method",
                            "name": "EchoHandler.post",
                            "content": "class EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 261,
                            "end_lineno": 262,
                            "parent": {
                                "file_name": "tornado/test/httpserver_test.py",
                                "type": "class",
                                "name": "EchoHandler",
                                "content": "class EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 257,
                                "end_lineno": 262,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 316,
                            "length": 6
                        },
                        "new_range": {
                            "start": 318,
                            "length": 11
                        },
                        "section": "class HTTPServerTest(AsyncHTTPTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        data = json_decode(response.body)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_empty_post_parameters(self):",
                                "type": "added"
                            },
                            {
                                "content": "        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")",
                                "type": "added"
                            },
                            {
                                "content": "        data = json_decode(response.body)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_types(self):",
                                "type": "context"
                            },
                            {
                                "content": "        headers = {\"Cookie\": \"foo=bar\"}",
                                "type": "context"
                            },
                            {
                                "content": "        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "class",
                            "name": "HTTPServerTest",
                            "content": "class HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 304,
                            "end_lineno": 350,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "method",
                            "name": "HTTPServerTest.test_empty_post_parameters",
                            "content": "class HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 321,
                            "end_lineno": 324,
                            "parent": {
                                "file_name": "tornado/test/httpserver_test.py",
                                "type": "class",
                                "name": "HTTPServerTest",
                                "content": "class HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 304,
                                "end_lineno": 350,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "ae166d72192d001be8c2b349a287a3027fb88db1^",
    "new_commit_hash": "ae166d72192d001be8c2b349a287a3027fb88db1",
    "commit_message": "Merge remote-tracking branch 'norman-labs/branch2.4'\n\nConflicts:\n\ttornado/httputil.py",
    "commit_date": "2013-03-14T21:42:49-04:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "ae166d72192d001be8c2b349a287a3027fb88db1",
    "test_file_codes": [
        "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import httpclient, simple_httpclient, netutil\nfrom tornado.escape import json_decode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context, Resolver\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.util import u, bytes_type\nfrom tornado.web import Application, RequestHandler, asynchronous\nimport datetime\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\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\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            self.http_client.fetch(self.get_url(\"/\").replace('https:', 'http:'),\n                                   self.stop,\n                                   request_timeout=3600,\n                                   connect_timeout=3600)\n            response = self.wait()\n        self.assertEqual(response.code, 599)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": \"/__mising__.crt\",\n                          })\n        self.assertRaises(ValueError, HTTPServer, application, ssl_options={\n                          \"certfile\": existing_certificate,\n                          \"keyfile\": \"/__missing__.key\"\n                          })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_certificate\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\nclass RawRequestHTTPConnection(simple_httpclient._HTTPConnection):\n    def set_request(self, request):\n        self.__next_request = request\n\n    def _on_connect(self):\n        self.stream.write(self.__next_request)\n        self.__next_request = None\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self._on_headers)\n\n# This test is also called from wsgi_test\n\n\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body):\n        client = SimpleAsyncHTTPClient(self.io_loop)\n        conn = RawRequestHTTPConnection(\n            self.io_loop, client,\n            httpclient._RequestProxy(\n                httpclient.HTTPRequest(self.get_url(\"/\")),\n                dict(httpclient.HTTPRequest._DEFAULTS)),\n            None, self.stop,\n            1024 * 1024, Resolver(io_loop=self.io_loop))\n        conn.set_request(\n            b\"\\r\\n\".join(headers +\n                         [utf8(\"Content-Length: %d\\r\\n\" % len(body))]) +\n            b\"\\r\\n\" + body)\n        response = self.wait()\n        client.close()\n        response.rethrow()\n        return response\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n            b\"Content-Disposition: form-data; name=argument\",\n            b\"\",\n            u(\"\\u00e1\").encode(\"utf-8\"),\n            b\"--1234567890\",\n            u('Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"').encode(\"utf8\"),\n            b\"\",\n            u(\"\\u00fa\").encode(\"utf-8\"),\n            b\"--1234567890--\",\n            b\"\",\n            ]))\n        data = json_decode(response.body)\n        self.assertEqual(u(\"\\u00e9\"), data[\"header\"])\n        self.assertEqual(u(\"\\u00e1\"), data[\"argument\"])\n        self.assertEqual(u(\"\\u00f3\"), data[\"filename\"])\n        self.assertEqual(u(\"\\u00fa\"), data[\"filebody\"])\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"localhost\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes_type)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes_type)\n        self.write(self.errors)\n\n    def get(self):\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 HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\\u00e9\")]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\"), u(\"\")]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_empty_request(self):\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n        stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n\n    def tearDown(self):\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        server = HTTPServer(app, io_loop=self.io_loop)\n        server.add_socket(sock)\n        stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        stream.connect(sockfile, self.stop)\n        self.wait()\n        stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.0 200 OK\\r\\n\")\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n        stream.close()\n        server.stop()\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('localhost', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(self.http_version + b' 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        headers = self.read_headers()\n        self.stream.read_bytes(int(headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\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",
        "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 817ms\nPrepared 1 package in 867ms\nInstalled 1 package in 1ms\n + tornado==2.4.post4 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1)\nResolved 29 packages in 12ms\nInstalled 29 packages in 147ms\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_ae166d72192d001be8c2b349a287a3027fb88db1\n...................................\ncollected 35 items\n\n=================================== ERRORS =====================================\n__________ BadSSLOptionsTest.test_missing_key __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 150, in test_missing_key\n    HTTPServer(application, ssl_options={\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/httpserver.py\", line 153, in __init__\n    TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 99, in __init__\n    raise ValueError('certfile \"%s\" does not exist' %\nValueError: certfile \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test.crt\" does not exist\n__________ SSLContextTest.test_large_post __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLContextTest.test_non_ssl_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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLContextTest.test_ssl __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLXHeaderTest.test_request_without_xprotocol __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 414, in test_request_without_xprotocol\n    self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 31, in fetch_json\n    response = self.fetch(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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::BadSSLOptionsTest::test_missing_arguments\nERROR r2e_tests.test_1::BadSSLOptionsTest::test_missing_key\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_100_continue\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_multipart_form\nPASSED r2e_tests.test_1::HTTPServerTest::test_double_slash\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_post_parameters\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_query_string\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_request\nPASSED r2e_tests.test_1::HTTPServerTest::test_query_string_encoding\nPASSED r2e_tests.test_1::HTTPServerTest::test_types\nPASSED r2e_tests.test_1::KeepAliveTest::test_cancel_during_download\nPASSED r2e_tests.test_1::KeepAliveTest::test_finish_while_closed\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_cancel\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_requests\nPASSED r2e_tests.test_1::KeepAliveTest::test_request_close\nPASSED r2e_tests.test_1::KeepAliveTest::test_two_requests\nPASSED r2e_tests.test_1::ManualProtocolTest::test_manual_protocol\nERROR r2e_tests.test_1::SSLContextTest::test_large_post\nERROR r2e_tests.test_1::SSLContextTest::test_non_ssl_request\nERROR r2e_tests.test_1::SSLContextTest::test_ssl\nERROR r2e_tests.test_1::SSLXHeaderTest::test_request_without_xprotocol\nERROR r2e_tests.test_1::SSLv23Test::test_large_post\nERROR r2e_tests.test_1::SSLv23Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv23Test::test_ssl\nERROR r2e_tests.test_1::SSLv3Test::test_large_post\nERROR r2e_tests.test_1::SSLv3Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv3Test::test_ssl\nERROR r2e_tests.test_1::TLSv1Test::test_large_post\nERROR r2e_tests.test_1::TLSv1Test::test_non_ssl_request\nERROR r2e_tests.test_1::TLSv1Test::test_ssl\nPASSED r2e_tests.test_1::UnixSocketTest::test_unix_socket\nPASSED r2e_tests.test_1::XHeaderTest::test_ip_headers\nPASSED r2e_tests.test_1::XHeaderTest::test_scheme_headers\n=================== 14 errors, 21 passed in 0.36s ===================\n",
    "new_commit_res_stderr": "",
    "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_ae166d72192d001be8c2b349a287a3027fb88db1\n...................................\ncollected 35 items\n\n=================================== FAILURES ===================================\n__________ HTTPServerTest.test_empty_post_parameters __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 324, in test_empty_post_parameters\n    self.assertEqual(data, {u(\"foo\"): [u(\"\")], u(\"bar\"): [u(\"\")]})\nAssertionError: {} != {'foo': [''], 'bar': ['']}\n- {}\n+ {'bar': [''], 'foo': ['']}\n\n=================================== ERRORS =====================================\n__________ BadSSLOptionsTest.test_missing_key __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 150, in test_missing_key\n    HTTPServer(application, ssl_options={\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/httpserver.py\", line 153, in __init__\n    TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 99, in __init__\n    raise ValueError('certfile \"%s\" does not exist' %\nValueError: certfile \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test.crt\" does not exist\n__________ SSLContextTest.test_large_post __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLContextTest.test_non_ssl_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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLContextTest.test_ssl __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 280, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 288, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 348, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 121, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLXHeaderTest.test_request_without_xprotocol __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 414, in test_request_without_xprotocol\n    self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 31, in fetch_json\n    response = self.fetch(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv23Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ SSLv3Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_large_post __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 78, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_non_ssl_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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 92, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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__________ TLSv1Test.test_ssl __________\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_ae166d72192d001be8c2b349a287a3027fb88db1/r2e_tests/test_1.py\", line 74, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 305, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 244, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/testing.py\", line 189, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/stack_context.py\", line 235, in wrapped\n    callback(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 141, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/tcpserver.py\", line 210, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 277, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_ae166d72192d001be8c2b349a287a3027fb88db1/tornado/netutil.py\", line 258, 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::BadSSLOptionsTest::test_missing_arguments\nERROR r2e_tests.test_1::BadSSLOptionsTest::test_missing_key\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_100_continue\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_multipart_form\nPASSED r2e_tests.test_1::HTTPServerTest::test_double_slash\nFAILED r2e_tests.test_1::HTTPServerTest::test_empty_post_parameters\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_query_string\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_request\nPASSED r2e_tests.test_1::HTTPServerTest::test_query_string_encoding\nPASSED r2e_tests.test_1::HTTPServerTest::test_types\nPASSED r2e_tests.test_1::KeepAliveTest::test_cancel_during_download\nPASSED r2e_tests.test_1::KeepAliveTest::test_finish_while_closed\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_cancel\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_requests\nPASSED r2e_tests.test_1::KeepAliveTest::test_request_close\nPASSED r2e_tests.test_1::KeepAliveTest::test_two_requests\nPASSED r2e_tests.test_1::ManualProtocolTest::test_manual_protocol\nERROR r2e_tests.test_1::SSLContextTest::test_large_post\nERROR r2e_tests.test_1::SSLContextTest::test_non_ssl_request\nERROR r2e_tests.test_1::SSLContextTest::test_ssl\nERROR r2e_tests.test_1::SSLXHeaderTest::test_request_without_xprotocol\nERROR r2e_tests.test_1::SSLv23Test::test_large_post\nERROR r2e_tests.test_1::SSLv23Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv23Test::test_ssl\nERROR r2e_tests.test_1::SSLv3Test::test_large_post\nERROR r2e_tests.test_1::SSLv3Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv3Test::test_ssl\nERROR r2e_tests.test_1::TLSv1Test::test_large_post\nERROR r2e_tests.test_1::TLSv1Test::test_non_ssl_request\nERROR r2e_tests.test_1::TLSv1Test::test_ssl\nPASSED r2e_tests.test_1::UnixSocketTest::test_unix_socket\nPASSED r2e_tests.test_1::XHeaderTest::test_ip_headers\nPASSED r2e_tests.test_1::XHeaderTest::test_scheme_headers\n=================== 1 failed, 14 errors, 20 passed in 0.26s ===================\n",
    "old_commit_res_stderr": ""
}
tornado/httputil.py tornado/test/httpserver_test.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** POST Requests with Empty Parameters Are Not Parsed Correctly

**Description:**
When sending a POST request with parameters that have empty values, the server fails to parse the parameters properly, resulting in missing arguments.

**Example:**
```python
response = self.fetch('/echo', method='POST', body='foo=&bar=')
data = json_decode(response.body)
# Expected data: {'foo': [''], 'bar': ['']}
# Actual data: {}
```

**Expected Behavior:**
The server should parse the POST parameters and include both 'foo' and 'bar' with empty strings as their values.

**Actual Behavior:**
The server returns an empty dictionary, omitting the parameters that have empty values.

[/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/httputil.py
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""HTTP utility code shared by clients and servers."""

from __future__ import absolute_import, division, print_function, with_statement

import datetime
import numbers
import re
import time

from tornado.escape import native_str, parse_qs_bytes, utf8
from tornado.log import gen_log
from tornado.util import ObjectDict

try:
    from httplib import responses  # py2
except ImportError:
    from http.client import responses  # py3

# responses is unused in this file, but we re-export it to other files.
# Reference it so pyflakes doesn't complain.
responses

try:
    from urllib import urlencode  # py2
except ImportError:
    from urllib.parse import urlencode  # py3


class HTTPHeaders(dict):
    """A dictionary that maintains Http-Header-Case for all keys.

    Supports multiple values per key via a pair of new methods,
    add() and get_list().  The regular dictionary interface returns a single
    value per key, with multiple values joined by a comma.

    >>> h = HTTPHeaders({"content-type": "text/html"})
    >>> list(h.keys())
    ['Content-Type']
    >>> h["Content-Type"]
    'text/html'

    >>> h.add("Set-Cookie", "A=B")
    >>> h.add("Set-Cookie", "C=D")
    >>> h["set-cookie"]
    'A=B,C=D'
    >>> h.get_list("set-cookie")
    ['A=B', 'C=D']

    >>> for (k,v) in sorted(h.get_all()):
    ...    print('%s: %s' % (k,v))
    ...
    Content-Type: text/html
    Set-Cookie: A=B
    Set-Cookie: C=D
    """
    def __init__(self, *args, **kwargs):
        # Don't pass args or kwargs to dict.__init__, as it will bypass
        # our __setitem__
        dict.__init__(self)
        self._as_list = {}
        self._last_key = None
        if (len(args) == 1 and len(kwargs) == 0 and
                isinstance(args[0], HTTPHeaders)):
            # Copy constructor
            for k, v in args[0].get_all():
                self.add(k, v)
        else:
            # Dict-style initialization
            self.update(*args, **kwargs)

    # new public methods

    def add(self, name, value):
        """Adds a new value for the given key."""
        norm_name = HTTPHeaders._normalize_name(name)
        self._last_key = norm_name
        if norm_name in self:
            # bypass our override of __setitem__ since it modifies _as_list
            dict.__setitem__(self, norm_name,
                             native_str(self[norm_name]) + ',' +
                             native_str(value))
            self._as_list[norm_name].append(value)
        else:
            self[norm_name] = value

    def get_list(self, name):
        """Returns all values for the given header as a list."""
        norm_name = HTTPHeaders._normalize_name(name)
        return self._as_list.get(norm_name, [])

    def get_all(self):
        """Returns an iterable of all (name, value) pairs.

        If a header has multiple values, multiple pairs will be
        returned with the same name.
        """
        for name, values in self._as_list.items():
            for value in values:
                yield (name, value)

    def parse_line(self, line):
        """Updates the dictionary with a single header line.

        >>> h = HTTPHeaders()
        >>> h.parse_line("Content-Type: text/html")
        >>> h.get('content-type')
        'text/html'
        """
        if line[0].isspace():
            # continuation of a multi-line header
            new_part = ' ' + line.lstrip()
            self._as_list[self._last_key][-1] += new_part
            dict.__setitem__(self, self._last_key,
                             self[self._last_key] + new_part)
        else:
            name, value = line.split(":", 1)
            self.add(name, value.strip())

    @classmethod
    def parse(cls, headers):
        """Returns a dictionary from HTTP header text.

        >>> h = HTTPHeaders.parse("Content-Type: text/html\\r\\nContent-Length: 42\\r\\n")
        >>> sorted(h.items())
        [('Content-Length', '42'), ('Content-Type', 'text/html')]
        """
        h = cls()
        for line in headers.splitlines():
            if line:
                h.parse_line(line)
        return h

    # dict implementation overrides

    def __setitem__(self, name, value):
        norm_name = HTTPHeaders._normalize_name(name)
        dict.__setitem__(self, norm_name, value)
        self._as_list[norm_name] = [value]

    def __getitem__(self, name):
        return dict.__getitem__(self, HTTPHeaders._normalize_name(name))

    def __delitem__(self, name):
        norm_name = HTTPHeaders._normalize_name(name)
        dict.__delitem__(self, norm_name)
        del self._as_list[norm_name]

    def __contains__(self, name):
        norm_name = HTTPHeaders._normalize_name(name)
        return dict.__contains__(self, norm_name)

    def get(self, name, default=None):
        return dict.get(self, HTTPHeaders._normalize_name(name), default)

    def update(self, *args, **kwargs):
        # dict.update bypasses our __setitem__
        for k, v in dict(*args, **kwargs).items():
            self[k] = v

    def copy(self):
        # default implementation returns dict(self), not the subclass
        return HTTPHeaders(self)

    _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')
    _normalized_headers = {}

    @staticmethod
    def _normalize_name(name):
        """Converts a name to Http-Header-Case.

        >>> HTTPHeaders._normalize_name("coNtent-TYPE")
        'Content-Type'
        """
        try:
            return HTTPHeaders._normalized_headers[name]
        except KeyError:
            if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):
                normalized = name
            else:
                normalized = "-".join([w.capitalize() for w in name.split("-")])
            HTTPHeaders._normalized_headers[name] = normalized
            return normalized


def url_concat(url, args):
    """Concatenate url and argument dictionary regardless of whether
    url has existing query parameters.

    >>> url_concat("http://example.com/foo?a=b", dict(c="d"))
    'http://example.com/foo?a=b&c=d'
    """
    if not args:
        return url
    if url[-1] not in ('?', '&'):
        url += '&' if ('?' in url) else '?'
    return url + urlencode(args)


class HTTPFile(ObjectDict):
    """Represents an HTTP file. For backwards compatibility, its instance
    attributes are also accessible as dictionary keys.

    :ivar filename:
    :ivar body:
    :ivar content_type: The content_type comes from the provided HTTP header
        and should not be trusted outright given that it can be easily forged.
    """
    pass


def parse_body_arguments(content_type, body, arguments, files):
    """Parses a form request body.

    Supports "application/x-www-form-urlencoded" and "multipart/form-data".
    The content_type parameter should be a string and body should be
    a byte string.  The arguments and files parameters are dictionaries
    that will be updated with the parsed contents.
    """
    if content_type.startswith("application/x-www-form-urlencoded"):
        uri_arguments = parse_qs_bytes(native_str(body))
        for name, values in uri_arguments.items():
            values = [v for v in values if v]
            if values:
                arguments.setdefault(name, []).extend(values)
    elif content_type.startswith("multipart/form-data"):
        fields = content_type.split(";")
        for field in fields:
            k, sep, v = field.strip().partition("=")
            if k == "boundary" and v:
                parse_multipart_form_data(utf8(v), body, arguments, files)
                break
        else:
            gen_log.warning("Invalid multipart/form-data")


def parse_multipart_form_data(boundary, data, arguments, files):
    """Parses a multipart/form-data body.

    The boundary and data parameters are both byte strings.
    The dictionaries given in the arguments and files parameters
    will be updated with the contents of the body.
    """
    # The standard allows for the boundary to be quoted in the header,
    # although it's rare (it happens at least for google app engine
    # xmpp).  I think we're also supposed to handle backslash-escapes
    # here but I'll save that until we see a client that uses them
    # in the wild.
    if boundary.startswith(b'"') and boundary.endswith(b'"'):
        boundary = boundary[1:-1]
    final_boundary_index = data.rfind(b"--" + boundary + b"--")
    if final_boundary_index == -1:
        gen_log.warning("Invalid multipart/form-data: no final boundary")
        return
    parts = data[:final_boundary_index].split(b"--" + boundary + b"\r\n")
    for part in parts:
        if not part:
            continue
        eoh = part.find(b"\r\n\r\n")
        if eoh == -1:
            gen_log.warning("multipart/form-data missing headers")
            continue
        headers = HTTPHeaders.parse(part[:eoh].decode("utf-8"))
        disp_header = headers.get("Content-Disposition", "")
        disposition, disp_params = _parse_header(disp_header)
        if disposition != "form-data" or not part.endswith(b"\r\n"):
            gen_log.warning("Invalid multipart/form-data")
            continue
        value = part[eoh + 4:-2]
        if not disp_params.get("name"):
            gen_log.warning("multipart/form-data value missing name")
            continue
        name = disp_params["name"]
        if disp_params.get("filename"):
            ctype = headers.get("Content-Type", "application/unknown")
            files.setdefault(name, []).append(HTTPFile(
                filename=disp_params["filename"], body=value,
                content_type=ctype))
        else:
            arguments.setdefault(name, []).append(value)


def format_timestamp(ts):
    """Formats a timestamp in the format used by HTTP.

    The argument may be a numeric timestamp as returned by `time.time()`,
    a time tuple as returned by `time.gmtime()`, or a `datetime.datetime`
    object.

    >>> format_timestamp(1359312200)
    'Sun, 27 Jan 2013 18:43:20 GMT'
    """
    if isinstance(ts, (tuple, time.struct_time)):
        pass
    elif isinstance(ts, datetime.datetime):
        ts = ts.utctimetuple()
    elif isinstance(ts, numbers.Real):
        ts = time.gmtime(ts)
    else:
        raise TypeError("unknown timestamp type: %r" % ts)
    return time.strftime("%a, %d %b %Y %H:%M:%S GMT", ts)

# _parseparam and _parse_header are copied and modified from python2.7's cgi.py
# The original 2.7 version of this code did not correctly support some
# combinations of semicolons and double quotes.


def _parseparam(s):
    while s[:1] == ';':
        s = s[1:]
        end = s.find(';')
        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
            end = s.find(';', end + 1)
        if end < 0:
            end = len(s)
        f = s[:end]
        yield f.strip()
        s = s[end:]


def _parse_header(line):
    """Parse a Content-type like header.

    Return the main content-type and a dictionary of options.

    """
    parts = _parseparam(';' + line)
    key = next(parts)
    pdict = {}
    for p in parts:
        i = p.find('=')
        if i >= 0:
            name = p[:i].strip().lower()
            value = p[i + 1:].strip()
            if len(value) >= 2 and value[0] == value[-1] == '"':
                value = value[1:-1]
                value = value.replace('\\\\', '\\').replace('\\"', '"')
            pdict[name] = value
    return key, pdict


def doctests():
    import doctest
    return doctest.DocTestSuite()

```
--- 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]

**Title:** POST Requests with Empty Parameters Are Not Parsed Correctly

**Description:**
When sending a POST request with parameters that have empty values, the server fails to parse the parameters properly, resulting in missing arguments.

**Example:**
```python
response = self.fetch('/echo', method='POST', body='foo=&bar=')
data = json_decode(response.body)
# Expected data: {'foo': [''], 'bar': ['']}
# Actual data: {}
```

**Expected Behavior:**
The server should parse the POST parameters and include both 'foo' and 'bar' with empty strings as their values.

**Actual Behavior:**
The server returns an empty dictionary, omitting the parameters that have empty values.

[/ISSUE]
{
    "BadSSLOptionsTest.test_missing_arguments": "PASSED",
    "BadSSLOptionsTest.test_missing_key": "ERROR",
    "HTTPConnectionTest.test_100_continue": "PASSED",
    "HTTPConnectionTest.test_multipart_form": "PASSED",
    "HTTPServerTest.test_double_slash": "PASSED",
    "HTTPServerTest.test_empty_post_parameters": "PASSED",
    "HTTPServerTest.test_empty_query_string": "PASSED",
    "HTTPServerTest.test_empty_request": "PASSED",
    "HTTPServerTest.test_query_string_encoding": "PASSED",
    "HTTPServerTest.test_types": "PASSED",
    "KeepAliveTest.test_cancel_during_download": "PASSED",
    "KeepAliveTest.test_finish_while_closed": "PASSED",
    "KeepAliveTest.test_http10": "PASSED",
    "KeepAliveTest.test_http10_keepalive": "PASSED",
    "KeepAliveTest.test_pipelined_cancel": "PASSED",
    "KeepAliveTest.test_pipelined_requests": "PASSED",
    "KeepAliveTest.test_request_close": "PASSED",
    "KeepAliveTest.test_two_requests": "PASSED",
    "ManualProtocolTest.test_manual_protocol": "PASSED",
    "SSLContextTest.test_large_post": "ERROR",
    "SSLContextTest.test_non_ssl_request": "ERROR",
    "SSLContextTest.test_ssl": "ERROR",
    "SSLXHeaderTest.test_request_without_xprotocol": "ERROR",
    "SSLv23Test.test_large_post": "ERROR",
    "SSLv23Test.test_non_ssl_request": "ERROR",
    "SSLv23Test.test_ssl": "ERROR",
    "SSLv3Test.test_large_post": "ERROR",
    "SSLv3Test.test_non_ssl_request": "ERROR",
    "SSLv3Test.test_ssl": "ERROR",
    "TLSv1Test.test_large_post": "ERROR",
    "TLSv1Test.test_non_ssl_request": "ERROR",
    "TLSv1Test.test_ssl": "ERROR",
    "UnixSocketTest.test_unix_socket": "PASSED",
    "XHeaderTest.test_ip_headers": "PASSED",
    "XHeaderTest.test_scheme_headers": "PASSED"
}
diff --git a/tornado/httputil.py b/tornado/httputil.py
index b9cd1065..f68c7414 100644
--- a/tornado/httputil.py
+++ b/tornado/httputil.py
@@ -236,6 +236,8 @@ def parse_body_arguments(content_type, body, arguments, files):
         uri_arguments = parse_qs_bytes(native_str(body))
         for name, values in uri_arguments.items():
             values = [v for v in values if v]
+        uri_arguments = parse_qs_bytes(native_str(body), keep_blank_values=True)
+        for name, values in uri_arguments.items():
             if values:
                 arguments.setdefault(name, []).extend(values)
     elif content_type.startswith("multipart/form-data"):

{"tornado/httputil.py": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"HTTP utility code shared by clients and servers.\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport datetime\nimport numbers\nimport re\nimport time\n\nfrom tornado.escape import native_str, parse_qs_bytes, utf8\nfrom tornado.log import gen_log\nfrom tornado.util import ObjectDict\n\ntry:\n    from httplib import responses  # py2\nexcept ImportError:\n    from http.client import responses  # py3\n\n# responses is unused in this file, but we re-export it to other files.\n# Reference it so pyflakes doesn't complain.\nresponses\n\ntry:\n    from urllib import urlencode  # py2\nexcept ImportError:\n    from urllib.parse import urlencode  # py3\n\n\nclass HTTPHeaders(dict):\n    \"\"\"A dictionary that maintains Http-Header-Case for all keys.\n\n    Supports multiple values per key via a pair of new methods,\n    add() and get_list().  The regular dictionary interface returns a single\n    value per key, with multiple values joined by a comma.\n\n    >>> h = HTTPHeaders({\"content-type\": \"text/html\"})\n    >>> list(h.keys())\n    ['Content-Type']\n    >>> h[\"Content-Type\"]\n    'text/html'\n\n    >>> h.add(\"Set-Cookie\", \"A=B\")\n    >>> h.add(\"Set-Cookie\", \"C=D\")\n    >>> h[\"set-cookie\"]\n    'A=B,C=D'\n    >>> h.get_list(\"set-cookie\")\n    ['A=B', 'C=D']\n\n    >>> for (k,v) in sorted(h.get_all()):\n    ...    print('%s: %s' % (k,v))\n    ...\n    Content-Type: text/html\n    Set-Cookie: A=B\n    Set-Cookie: C=D\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        # Don't pass args or kwargs to dict.__init__, as it will bypass\n        # our __setitem__\n        dict.__init__(self)\n        self._as_list = {}\n        self._last_key = None\n        if (len(args) == 1 and len(kwargs) == 0 and\n                isinstance(args[0], HTTPHeaders)):\n            # Copy constructor\n            for k, v in args[0].get_all():\n                self.add(k, v)\n        else:\n            # Dict-style initialization\n            self.update(*args, **kwargs)\n\n    # new public methods\n\n    def add(self, name, value):\n        \"\"\"Adds a new value for the given key.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        self._last_key = norm_name\n        if norm_name in self:\n            # bypass our override of __setitem__ since it modifies _as_list\n            dict.__setitem__(self, norm_name,\n                             native_str(self[norm_name]) + ',' +\n                             native_str(value))\n            self._as_list[norm_name].append(value)\n        else:\n            self[norm_name] = value\n\n    def get_list(self, name):\n        \"\"\"Returns all values for the given header as a list.\"\"\"\n        norm_name = HTTPHeaders._normalize_name(name)\n        return self._as_list.get(norm_name, [])\n\n    def get_all(self):\n        \"\"\"Returns an iterable of all (name, value) pairs.\n\n        If a header has multiple values, multiple pairs will be\n        returned with the same name.\n        \"\"\"\n        for name, values in self._as_list.items():\n            for value in values:\n                yield (name, value)\n\n    def parse_line(self, line):\n        \"\"\"Updates the dictionary with a single header line.\n\n        >>> h = HTTPHeaders()\n        >>> h.parse_line(\"Content-Type: text/html\")\n        >>> h.get('content-type')\n        'text/html'\n        \"\"\"\n        if line[0].isspace():\n            # continuation of a multi-line header\n            new_part = ' ' + line.lstrip()\n            self._as_list[self._last_key][-1] += new_part\n            dict.__setitem__(self, self._last_key,\n                             self[self._last_key] + new_part)\n        else:\n            name, value = line.split(\":\", 1)\n            self.add(name, value.strip())\n\n    @classmethod\n    def parse(cls, headers):\n        \"\"\"Returns a dictionary from HTTP header text.\n\n        >>> h = HTTPHeaders.parse(\"Content-Type: text/html\\\\r\\\\nContent-Length: 42\\\\r\\\\n\")\n        >>> sorted(h.items())\n        [('Content-Length', '42'), ('Content-Type', 'text/html')]\n        \"\"\"\n        h = cls()\n        for line in headers.splitlines():\n            if line:\n                h.parse_line(line)\n        return h\n\n    # dict implementation overrides\n\n    def __setitem__(self, name, value):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__setitem__(self, norm_name, value)\n        self._as_list[norm_name] = [value]\n\n    def __getitem__(self, name):\n        return dict.__getitem__(self, HTTPHeaders._normalize_name(name))\n\n    def __delitem__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        dict.__delitem__(self, norm_name)\n        del self._as_list[norm_name]\n\n    def __contains__(self, name):\n        norm_name = HTTPHeaders._normalize_name(name)\n        return dict.__contains__(self, norm_name)\n\n    def get(self, name, default=None):\n        return dict.get(self, HTTPHeaders._normalize_name(name), default)\n\n    def update(self, *args, **kwargs):\n        # dict.update bypasses our __setitem__\n        for k, v in dict(*args, **kwargs).items():\n            self[k] = v\n\n    def copy(self):\n        # default implementation returns dict(self), not the subclass\n        return HTTPHeaders(self)\n\n    _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')\n    _normalized_headers = {}\n\n    @staticmethod\n    def _normalize_name(name):\n        \"\"\"Converts a name to Http-Header-Case.\n\n        >>> HTTPHeaders._normalize_name(\"coNtent-TYPE\")\n        'Content-Type'\n        \"\"\"\n        try:\n            return HTTPHeaders._normalized_headers[name]\n        except KeyError:\n            if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):\n                normalized = name\n            else:\n                normalized = \"-\".join([w.capitalize() for w in name.split(\"-\")])\n            HTTPHeaders._normalized_headers[name] = normalized\n            return normalized\n\n\ndef url_concat(url, args):\n    \"\"\"Concatenate url and argument dictionary regardless of whether\n    url has existing query parameters.\n\n    >>> url_concat(\"http://example.com/foo?a=b\", dict(c=\"d\"))\n    'http://example.com/foo?a=b&c=d'\n    \"\"\"\n    if not args:\n        return url\n    if url[-1] not in ('?', '&'):\n        url += '&' if ('?' in url) else '?'\n    return url + urlencode(args)\n\n\nclass HTTPFile(ObjectDict):\n    \"\"\"Represents an HTTP file. For backwards compatibility, its instance\n    attributes are also accessible as dictionary keys.\n\n    :ivar filename:\n    :ivar body:\n    :ivar content_type: The content_type comes from the provided HTTP header\n        and should not be trusted outright given that it can be easily forged.\n    \"\"\"\n    pass\n\n\ndef parse_body_arguments(content_type, body, arguments, files):\n    \"\"\"Parses a form request body.\n\n    Supports \"application/x-www-form-urlencoded\" and \"multipart/form-data\".\n    The content_type parameter should be a string and body should be\n    a byte string.  The arguments and files parameters are dictionaries\n    that will be updated with the parsed contents.\n    \"\"\"\n    if content_type.startswith(\"application/x-www-form-urlencoded\"):\n        uri_arguments = parse_qs_bytes(native_str(body))\n        for name, values in uri_arguments.items():\n            values = [v for v in values if v]\n            if values:\n                arguments.setdefault(name, []).extend(values)\n    elif content_type.startswith(\"multipart/form-data\"):\n        fields = content_type.split(\";\")\n        for field in fields:\n            k, sep, v = field.strip().partition(\"=\")\n            if k == \"boundary\" and v:\n                parse_multipart_form_data(utf8(v), body, arguments, files)\n                break\n        else:\n            gen_log.warning(\"Invalid multipart/form-data\")\n\n\ndef parse_multipart_form_data(boundary, data, arguments, files):\n    \"\"\"Parses a multipart/form-data body.\n\n    The boundary and data parameters are both byte strings.\n    The dictionaries given in the arguments and files parameters\n    will be updated with the contents of the body.\n    \"\"\"\n    # The standard allows for the boundary to be quoted in the header,\n    # although it's rare (it happens at least for google app engine\n    # xmpp).  I think we're also supposed to handle backslash-escapes\n    # here but I'll save that until we see a client that uses them\n    # in the wild.\n    if boundary.startswith(b'\"') and boundary.endswith(b'\"'):\n        boundary = boundary[1:-1]\n    final_boundary_index = data.rfind(b\"--\" + boundary + b\"--\")\n    if final_boundary_index == -1:\n        gen_log.warning(\"Invalid multipart/form-data: no final boundary\")\n        return\n    parts = data[:final_boundary_index].split(b\"--\" + boundary + b\"\\r\\n\")\n    for part in parts:\n        if not part:\n            continue\n        eoh = part.find(b\"\\r\\n\\r\\n\")\n        if eoh == -1:\n            gen_log.warning(\"multipart/form-data missing headers\")\n            continue\n        headers = HTTPHeaders.parse(part[:eoh].decode(\"utf-8\"))\n        disp_header = headers.get(\"Content-Disposition\", \"\")\n        disposition, disp_params = _parse_header(disp_header)\n        if disposition != \"form-data\" or not part.endswith(b\"\\r\\n\"):\n            gen_log.warning(\"Invalid multipart/form-data\")\n            continue\n        value = part[eoh + 4:-2]\n        if not disp_params.get(\"name\"):\n            gen_log.warning(\"multipart/form-data value missing name\")\n            continue\n        name = disp_params[\"name\"]\n        if disp_params.get(\"filename\"):\n            ctype = headers.get(\"Content-Type\", \"application/unknown\")\n            files.setdefault(name, []).append(HTTPFile(\n                filename=disp_params[\"filename\"], body=value,\n                content_type=ctype))\n        else:\n            arguments.setdefault(name, []).append(value)\n\n\ndef format_timestamp(ts):\n    \"\"\"Formats a timestamp in the format used by HTTP.\n\n    The argument may be a numeric timestamp as returned by `time.time()`,\n    a time tuple as returned by `time.gmtime()`, or a `datetime.datetime`\n    object.\n\n    >>> format_timestamp(1359312200)\n    'Sun, 27 Jan 2013 18:43:20 GMT'\n    \"\"\"\n    if isinstance(ts, (tuple, time.struct_time)):\n        pass\n    elif isinstance(ts, datetime.datetime):\n        ts = ts.utctimetuple()\n    elif isinstance(ts, numbers.Real):\n        ts = time.gmtime(ts)\n    else:\n        raise TypeError(\"unknown timestamp type: %r\" % ts)\n    return time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", ts)\n\n# _parseparam and _parse_header are copied and modified from python2.7's cgi.py\n# The original 2.7 version of this code did not correctly support some\n# combinations of semicolons and double quotes.\n\n\ndef _parseparam(s):\n    while s[:1] == ';':\n        s = s[1:]\n        end = s.find(';')\n        while end > 0 and (s.count('\"', 0, end) - s.count('\\\\\"', 0, end)) % 2:\n            end = s.find(';', end + 1)\n        if end < 0:\n            end = len(s)\n        f = s[:end]\n        yield f.strip()\n        s = s[end:]\n\n\ndef _parse_header(line):\n    \"\"\"Parse a Content-type like header.\n\n    Return the main content-type and a dictionary of options.\n\n    \"\"\"\n    parts = _parseparam(';' + line)\n    key = next(parts)\n    pdict = {}\n    for p in parts:\n        i = p.find('=')\n        if i >= 0:\n            name = p[:i].strip().lower()\n            value = p[i + 1:].strip()\n            if len(value) >= 2 and value[0] == value[-1] == '\"':\n                value = value[1:-1]\n                value = value.replace('\\\\\\\\', '\\\\').replace('\\\\\"', '\"')\n            pdict[name] = value\n    return key, pdict\n\n\ndef doctests():\n    import doctest\n    return doctest.DocTestSuite()\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]

**Title:** POST Requests with Empty Parameters Are Not Parsed Correctly

**Description:**
When sending a POST request with parameters that have empty values, the server fails to parse the parameters properly, resulting in missing arguments.

**Example:**
```python
response = self.fetch('/echo', method='POST', body='foo=&bar=')
data = json_decode(response.body)
# Expected data: {'foo': [''], 'bar': ['']}
# Actual data: {}
```

**Expected Behavior:**
The server should parse the POST parameters and include both 'foo' and 'bar' with empty strings as their values.

**Actual Behavior:**
The server returns an empty dictionary, omitting the parameters that have empty values.

[/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/httputil.py
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""HTTP utility code shared by clients and servers."""

from __future__ import absolute_import, division, print_function, with_statement

import datetime
import numbers
import re
import time

from tornado.escape import native_str, parse_qs_bytes, utf8
from tornado.log import gen_log
from tornado.util import ObjectDict

try:
    from httplib import responses  # py2
except ImportError:
    from http.client import responses  # py3

# responses is unused in this file, but we re-export it to other files.
# Reference it so pyflakes doesn't complain.
responses

try:
    from urllib import urlencode  # py2
except ImportError:
    from urllib.parse import urlencode  # py3


class HTTPHeaders(dict):
    """A dictionary that maintains Http-Header-Case for all keys.

    Supports multiple values per key via a pair of new methods,
    add() and get_list().  The regular dictionary interface returns a single
    value per key, with multiple values joined by a comma.

    >>> h = HTTPHeaders({"content-type": "text/html"})
    >>> list(h.keys())
    ['Content-Type']
    >>> h["Content-Type"]
    'text/html'

    >>> h.add("Set-Cookie", "A=B")
    >>> h.add("Set-Cookie", "C=D")
    >>> h["set-cookie"]
    'A=B,C=D'
    >>> h.get_list("set-cookie")
    ['A=B', 'C=D']

    >>> for (k,v) in sorted(h.get_all()):
    ...    print('%s: %s' % (k,v))
    ...
    Content-Type: text/html
    Set-Cookie: A=B
    Set-Cookie: C=D
    """
    def __init__(self, *args, **kwargs):
        # Don't pass args or kwargs to dict.__init__, as it will bypass
        # our __setitem__
        dict.__init__(self)
        self._as_list = {}
        self._last_key = None
        if (len(args) == 1 and len(kwargs) == 0 and
                isinstance(args[0], HTTPHeaders)):
            # Copy constructor
            for k, v in args[0].get_all():
                self.add(k, v)
        else:
            # Dict-style initialization
            self.update(*args, **kwargs)

    # new public methods

    def add(self, name, value):
        """Adds a new value for the given key."""
        norm_name = HTTPHeaders._normalize_name(name)
        self._last_key = norm_name
        if norm_name in self:
            # bypass our override of __setitem__ since it modifies _as_list
            dict.__setitem__(self, norm_name,
                             native_str(self[norm_name]) + ',' +
                             native_str(value))
            self._as_list[norm_name].append(value)
        else:
            self[norm_name] = value

    def get_list(self, name):
        """Returns all values for the given header as a list."""
        norm_name = HTTPHeaders._normalize_name(name)
        return self._as_list.get(norm_name, [])

    def get_all(self):
        """Returns an iterable of all (name, value) pairs.

        If a header has multiple values, multiple pairs will be
        returned with the same name.
        """
        for name, values in self._as_list.items():
            for value in values:
                yield (name, value)

    def parse_line(self, line):
        """Updates the dictionary with a single header line.

        >>> h = HTTPHeaders()
        >>> h.parse_line("Content-Type: text/html")
        >>> h.get('content-type')
        'text/html'
        """
        if line[0].isspace():
            # continuation of a multi-line header
            new_part = ' ' + line.lstrip()
            self._as_list[self._last_key][-1] += new_part
            dict.__setitem__(self, self._last_key,
                             self[self._last_key] + new_part)
        else:
            name, value = line.split(":", 1)
            self.add(name, value.strip())

    @classmethod
    def parse(cls, headers):
        """Returns a dictionary from HTTP header text.

        >>> h = HTTPHeaders.parse("Content-Type: text/html\\r\\nContent-Length: 42\\r\\n")
        >>> sorted(h.items())
        [('Content-Length', '42'), ('Content-Type', 'text/html')]
        """
        h = cls()
        for line in headers.splitlines():
            if line:
                h.parse_line(line)
        return h

    # dict implementation overrides

    def __setitem__(self, name, value):
        norm_name = HTTPHeaders._normalize_name(name)
        dict.__setitem__(self, norm_name, value)
        self._as_list[norm_name] = [value]

    def __getitem__(self, name):
        return dict.__getitem__(self, HTTPHeaders._normalize_name(name))

    def __delitem__(self, name):
        norm_name = HTTPHeaders._normalize_name(name)
        dict.__delitem__(self, norm_name)
        del self._as_list[norm_name]

    def __contains__(self, name):
        norm_name = HTTPHeaders._normalize_name(name)
        return dict.__contains__(self, norm_name)

    def get(self, name, default=None):
        return dict.get(self, HTTPHeaders._normalize_name(name), default)

    def update(self, *args, **kwargs):
        # dict.update bypasses our __setitem__
        for k, v in dict(*args, **kwargs).items():
            self[k] = v

    def copy(self):
        # default implementation returns dict(self), not the subclass
        return HTTPHeaders(self)

    _NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')
    _normalized_headers = {}

    @staticmethod
    def _normalize_name(name):
        """Converts a name to Http-Header-Case.

        >>> HTTPHeaders._normalize_name("coNtent-TYPE")
        'Content-Type'
        """
        try:
            return HTTPHeaders._normalized_headers[name]
        except KeyError:
            if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):
                normalized = name
            else:
                normalized = "-".join([w.capitalize() for w in name.split("-")])
            HTTPHeaders._normalized_headers[name] = normalized
            return normalized


def url_concat(url, args):
    """Concatenate url and argument dictionary regardless of whether
    url has existing query parameters.

    >>> url_concat("http://example.com/foo?a=b", dict(c="d"))
    'http://example.com/foo?a=b&c=d'
    """
    if not args:
        return url
    if url[-1] not in ('?', '&'):
        url += '&' if ('?' in url) else '?'
    return url + urlencode(args)


class HTTPFile(ObjectDict):
    """Represents an HTTP file. For backwards compatibility, its instance
    attributes are also accessible as dictionary keys.

    :ivar filename:
    :ivar body:
    :ivar content_type: The content_type comes from the provided HTTP header
        and should not be trusted outright given that it can be easily forged.
    """
    pass


def parse_body_arguments(content_type, body, arguments, files):
    """Parses a form request body.

    Supports "application/x-www-form-urlencoded" and "multipart/form-data".
    The content_type parameter should be a string and body should be
    a byte string.  The arguments and files parameters are dictionaries
    that will be updated with the parsed contents.
    """
    if content_type.startswith("application/x-www-form-urlencoded"):
        uri_arguments = parse_qs_bytes(native_str(body))
        for name, values in uri_arguments.items():
            values = [v for v in values if v]
            if values:
                arguments.setdefault(name, []).extend(values)
    elif content_type.startswith("multipart/form-data"):
        fields = content_type.split(";")
        for field in fields:
            k, sep, v = field.strip().partition("=")
            if k == "boundary" and v:
                parse_multipart_form_data(utf8(v), body, arguments, files)
                break
        else:
            gen_log.warning("Invalid multipart/form-data")


def parse_multipart_form_data(boundary, data, arguments, files):
    """Parses a multipart/form-data body.

    The boundary and data parameters are both byte strings.
    The dictionaries given in the arguments and files parameters
    will be updated with the contents of the body.
    """
    # The standard allows for the boundary to be quoted in the header,
    # although it's rare (it happens at least for google app engine
    # xmpp).  I think we're also supposed to handle backslash-escapes
    # here but I'll save that until we see a client that uses them
    # in the wild.
    if boundary.startswith(b'"') and boundary.endswith(b'"'):
        boundary = boundary[1:-1]
    final_boundary_index = data.rfind(b"--" + boundary + b"--")
    if final_boundary_index == -1:
        gen_log.warning("Invalid multipart/form-data: no final boundary")
        return
    parts = data[:final_boundary_index].split(b"--" + boundary + b"\r\n")
    for part in parts:
        if not part:
            continue
        eoh = part.find(b"\r\n\r\n")
        if eoh == -1:
            gen_log.warning("multipart/form-data missing headers")
            continue
        headers = HTTPHeaders.parse(part[:eoh].decode("utf-8"))
        disp_header = headers.get("Content-Disposition", "")
        disposition, disp_params = _parse_header(disp_header)
        if disposition != "form-data" or not part.endswith(b"\r\n"):
            gen_log.warning("Invalid multipart/form-data")
            continue
        value = part[eoh + 4:-2]
        if not disp_params.get("name"):
            gen_log.warning("multipart/form-data value missing name")
            continue
        name = disp_params["name"]
        if disp_params.get("filename"):
            ctype = headers.get("Content-Type", "application/unknown")
            files.setdefault(name, []).append(HTTPFile(
                filename=disp_params["filename"], body=value,
                content_type=ctype))
        else:
            arguments.setdefault(name, []).append(value)


def format_timestamp(ts):
    """Formats a timestamp in the format used by HTTP.

    The argument may be a numeric timestamp as returned by `time.time()`,
    a time tuple as returned by `time.gmtime()`, or a `datetime.datetime`
    object.

    >>> format_timestamp(1359312200)
    'Sun, 27 Jan 2013 18:43:20 GMT'
    """
    if isinstance(ts, (tuple, time.struct_time)):
        pass
    elif isinstance(ts, datetime.datetime):
        ts = ts.utctimetuple()
    elif isinstance(ts, numbers.Real):
        ts = time.gmtime(ts)
    else:
        raise TypeError("unknown timestamp type: %r" % ts)
    return time.strftime("%a, %d %b %Y %H:%M:%S GMT", ts)

# _parseparam and _parse_header are copied and modified from python2.7's cgi.py
# The original 2.7 version of this code did not correctly support some
# combinations of semicolons and double quotes.


def _parseparam(s):
    while s[:1] == ';':
        s = s[1:]
        end = s.find(';')
        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
            end = s.find(';', end + 1)
        if end < 0:
            end = len(s)
        f = s[:end]
        yield f.strip()
        s = s[end:]


def _parse_header(line):
    """Parse a Content-type like header.

    Return the main content-type and a dictionary of options.

    """
    parts = _parseparam(';' + line)
    key = next(parts)
    pdict = {}
    for p in parts:
        i = p.find('=')
        if i >= 0:
            name = p[:i].strip().lower()
            value = p[i + 1:].strip()
            if len(value) >= 2 and value[0] == value[-1] == '"':
                value = value[1:-1]
                value = value.replace('\\\\', '\\').replace('\\"', '"')
            pdict[name] = value
    return key, pdict


def doctests():
    import doctest
    return doctest.DocTestSuite()

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