Add python-eventlet package to MOS 8.0 repository
[packages/trusty/python-eventlet.git] / eventlet / tests / wsgi_test.py
diff --git a/eventlet/tests/wsgi_test.py b/eventlet/tests/wsgi_test.py
deleted file mode 100644 (file)
index 179881d..0000000
+++ /dev/null
@@ -1,1755 +0,0 @@
-import cgi
-import collections
-import errno
-import os
-import signal
-import socket
-import sys
-import traceback
-import unittest
-
-import eventlet
-from eventlet import debug
-from eventlet import event
-from eventlet.green import socket as greensocket
-from eventlet.green import ssl
-from eventlet.green import subprocess
-from eventlet import greenio
-from eventlet import greenthread
-from eventlet import support
-from eventlet.support import bytes_to_str, capture_stderr, six
-from eventlet import tpool
-from eventlet import wsgi
-
-import tests
-
-
-certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-
-
-HttpReadResult = collections.namedtuple(
-    'HttpReadResult',
-    'status headers_lower body headers_original')
-
-
-def hello_world(env, start_response):
-    if env['PATH_INFO'] == 'notexist':
-        start_response('404 Not Found', [('Content-type', 'text/plain')])
-        return [b"not found"]
-
-    start_response('200 OK', [('Content-type', 'text/plain')])
-    return [b"hello world"]
-
-
-def chunked_app(env, start_response):
-    start_response('200 OK', [('Content-type', 'text/plain')])
-    yield b"this"
-    yield b"is"
-    yield b"chunked"
-
-
-def chunked_fail_app(environ, start_response):
-    """http://rhodesmill.org/brandon/2013/chunked-wsgi/
-    """
-    headers = [('Content-Type', 'text/plain')]
-    start_response('200 OK', headers)
-
-    # We start streaming data just fine.
-    yield b"The dwarves of yore made mighty spells,"
-    yield b"While hammers fell like ringing bells"
-
-    # Then the back-end fails!
-    try:
-        1 / 0
-    except Exception:
-        start_response('500 Error', headers, sys.exc_info())
-        return
-
-    # So rest of the response data is not available.
-    yield b"In places deep, where dark things sleep,"
-    yield b"In hollow halls beneath the fells."
-
-
-def big_chunks(env, start_response):
-    start_response('200 OK', [('Content-type', 'text/plain')])
-    line = b'a' * 8192
-    for x in range(10):
-        yield line
-
-
-def use_write(env, start_response):
-    if env['PATH_INFO'] == '/a':
-        write = start_response('200 OK', [('Content-type', 'text/plain'),
-                                          ('Content-Length', '5')])
-        write(b'abcde')
-    if env['PATH_INFO'] == '/b':
-        write = start_response('200 OK', [('Content-type', 'text/plain')])
-        write(b'abcde')
-    return []
-
-
-def chunked_post(env, start_response):
-    start_response('200 OK', [('Content-type', 'text/plain')])
-    if env['PATH_INFO'] == '/a':
-        return [env['wsgi.input'].read()]
-    elif env['PATH_INFO'] == '/b':
-        return [x for x in iter(lambda: env['wsgi.input'].read(4096), b'')]
-    elif env['PATH_INFO'] == '/c':
-        return [x for x in iter(lambda: env['wsgi.input'].read(1), b'')]
-
-
-def already_handled(env, start_response):
-    start_response('200 OK', [('Content-type', 'text/plain')])
-    return wsgi.ALREADY_HANDLED
-
-
-class Site(object):
-    def __init__(self):
-        self.application = hello_world
-
-    def __call__(self, env, start_response):
-        return self.application(env, start_response)
-
-
-class IterableApp(object):
-
-    def __init__(self, send_start_response=False, return_val=wsgi.ALREADY_HANDLED):
-        self.send_start_response = send_start_response
-        self.return_val = return_val
-        self.env = {}
-
-    def __call__(self, env, start_response):
-        self.env = env
-        if self.send_start_response:
-            start_response('200 OK', [('Content-type', 'text/plain')])
-        return self.return_val
-
-
-class IterableSite(Site):
-    def __call__(self, env, start_response):
-        it = self.application(env, start_response)
-        for i in it:
-            yield i
-
-
-CONTENT_LENGTH = 'content-length'
-
-
-"""
-HTTP/1.1 200 OK
-Date: foo
-Content-length: 11
-
-hello world
-"""
-
-
-def recvall(socket_):
-    result = b''
-    while True:
-        chunk = socket_.recv()
-        result += chunk
-        if chunk == b'':
-            break
-
-    return result
-
-
-class ConnectionClosed(Exception):
-    pass
-
-
-def send_expect_close(sock, buf):
-    # Some tests will induce behavior that causes the remote end to
-    # close the connection before all of the data has been written.
-    # With small kernel buffer sizes, this can cause an EPIPE error.
-    # Since the test expects an early close, this can be ignored.
-    try:
-        sock.sendall(buf)
-    except socket.error as exc:
-        if support.get_errno(exc) != errno.EPIPE:
-            raise
-
-
-def read_http(sock):
-    fd = sock.makefile('rb')
-    try:
-        response_line = bytes_to_str(fd.readline().rstrip(b'\r\n'))
-    except socket.error as exc:
-        # TODO find out whether 54 is ok here or not, I see it when running tests
-        # on Python 3
-        if support.get_errno(exc) in (10053, 54):
-            raise ConnectionClosed
-        raise
-    if not response_line:
-        raise ConnectionClosed(response_line)
-
-    header_lines = []
-    while True:
-        line = fd.readline()
-        if line == b'\r\n':
-            break
-        else:
-            header_lines.append(line)
-
-    headers_original = {}
-    headers_lower = {}
-    for x in header_lines:
-        x = x.strip()
-        if not x:
-            continue
-        key, value = bytes_to_str(x).split(':', 1)
-        key = key.rstrip()
-        value = value.lstrip()
-        key_lower = key.lower()
-        # FIXME: Duplicate headers are allowed as per HTTP RFC standard,
-        # the client and/or intermediate proxies are supposed to treat them
-        # as a single header with values concatenated using space (' ') delimiter.
-        assert key_lower not in headers_lower, "header duplicated: {0}".format(key)
-        headers_original[key] = value
-        headers_lower[key_lower] = value
-
-    content_length_str = headers_lower.get(CONTENT_LENGTH.lower(), '')
-    if content_length_str:
-        num = int(content_length_str)
-        body = fd.read(num)
-    else:
-        # read until EOF
-        body = fd.read()
-
-    result = HttpReadResult(
-        status=response_line,
-        headers_lower=headers_lower,
-        body=body,
-        headers_original=headers_original)
-    return result
-
-
-class _TestBase(tests.LimitedTestCase):
-    def setUp(self):
-        super(_TestBase, self).setUp()
-        self.logfile = six.StringIO()
-        self.site = Site()
-        self.killer = None
-        self.set_site()
-        self.spawn_server()
-
-    def tearDown(self):
-        greenthread.kill(self.killer)
-        eventlet.sleep(0)
-        super(_TestBase, self).tearDown()
-
-    def spawn_server(self, **kwargs):
-        """Spawns a new wsgi server with the given arguments using
-        :meth:`spawn_thread`.
-
-        Sets self.port to the port of the server
-        """
-        new_kwargs = dict(max_size=128,
-                          log=self.logfile,
-                          site=self.site)
-        new_kwargs.update(kwargs)
-
-        if 'sock' not in new_kwargs:
-            new_kwargs['sock'] = eventlet.listen(('localhost', 0))
-
-        self.port = new_kwargs['sock'].getsockname()[1]
-        self.spawn_thread(wsgi.server, **new_kwargs)
-
-    def spawn_thread(self, target, **kwargs):
-        """Spawns a new greenthread using specified target and arguments.
-
-        Kills any previously-running server and sets self.killer to the
-        greenthread running the target.
-        """
-        eventlet.sleep(0)  # give previous server a chance to start
-        if self.killer:
-            greenthread.kill(self.killer)
-
-        self.killer = eventlet.spawn_n(target, **kwargs)
-
-    def set_site(self):
-        raise NotImplementedError
-
-
-class TestHttpd(_TestBase):
-    def set_site(self):
-        self.site = Site()
-
-    def test_001_server(self):
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result = fd.read()
-        fd.close()
-        # The server responds with the maximum version it supports
-        assert result.startswith(b'HTTP'), result
-        assert result.endswith(b'hello world'), result
-
-    def test_002_keepalive(self):
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        read_http(sock)
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        read_http(sock)
-        fd.close()
-        sock.close()
-
-    def test_003_passing_non_int_to_read(self):
-        # This should go in greenio_test
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        cancel = eventlet.Timeout(1, RuntimeError)
-        self.assertRaises(TypeError, fd.read, "This shouldn't work")
-        cancel.cancel()
-        fd.close()
-
-    def test_004_close_keepalive(self):
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        read_http(sock)
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        read_http(sock)
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        self.assertRaises(ConnectionClosed, read_http, sock)
-        fd.close()
-
-    @tests.skipped
-    def test_005_run_apachebench(self):
-        url = 'http://localhost:12346/'
-        # ab is apachebench
-        subprocess.call(
-            [tests.find_command('ab'), '-c', '64', '-n', '1024', '-k', url],
-            stdout=subprocess.PIPE)
-
-    def test_006_reject_long_urls(self):
-        sock = eventlet.connect(
-            ('localhost', self.port))
-        path_parts = []
-        for ii in range(3000):
-            path_parts.append('path')
-        path = '/'.join(path_parts)
-        request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
-        send_expect_close(sock, request.encode())
-        fd = sock.makefile('rb')
-        result = fd.readline()
-        if result:
-            # windows closes the socket before the data is flushed,
-            # so we never get anything back
-            status = result.split(b' ')[1]
-            self.assertEqual(status, b'414')
-        fd.close()
-
-    def test_007_get_arg(self):
-        # define a new handler that does a get_arg as well as a read_body
-        def new_app(env, start_response):
-            body = bytes_to_str(env['wsgi.input'].read())
-            a = cgi.parse_qs(body).get('a', [1])[0]
-            start_response('200 OK', [('Content-type', 'text/plain')])
-            return [six.b('a is %s, body is %s' % (a, body))]
-
-        self.site.application = new_app
-        sock = eventlet.connect(
-            ('localhost', self.port))
-        request = '\r\n'.join((
-            'POST / HTTP/1.0',
-            'Host: localhost',
-            'Content-Length: 3',
-            '',
-            'a=a'))
-        fd = sock.makefile('wb')
-        fd.write(request.encode())
-        fd.flush()
-
-        # send some junk after the actual request
-        fd.write(b'01234567890123456789')
-        result = read_http(sock)
-        self.assertEqual(result.body, b'a is a, body is a=a')
-        fd.close()
-
-    def test_008_correctresponse(self):
-        sock = eventlet.connect(('localhost', self.port))
-
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result_200 = read_http(sock)
-        fd.write(b'GET /notexist HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        read_http(sock)
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result_test = read_http(sock)
-        self.assertEqual(result_200.status, result_test.status)
-        fd.close()
-        sock.close()
-
-    def test_009_chunked_response(self):
-        self.site.application = chunked_app
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        assert b'Transfer-Encoding: chunked' in fd.read()
-
-    def test_010_no_chunked_http_1_0(self):
-        self.site.application = chunked_app
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        assert b'Transfer-Encoding: chunked' not in fd.read()
-
-    def test_011_multiple_chunks(self):
-        self.site.application = big_chunks
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        headers = b''
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                headers += line
-        assert b'Transfer-Encoding: chunked' in headers
-        chunks = 0
-        chunklen = int(fd.readline(), 16)
-        while chunklen:
-            chunks += 1
-            fd.read(chunklen)
-            fd.readline()  # CRLF
-            chunklen = int(fd.readline(), 16)
-        assert chunks > 1
-        response = fd.read()
-        # Require a CRLF to close the message body
-        self.assertEqual(response, b'\r\n')
-
-    @tests.skip_if_no_ssl
-    def test_012_ssl_server(self):
-        def wsgi_app(environ, start_response):
-            start_response('200 OK', {})
-            return [environ['wsgi.input'].read()]
-
-        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-
-        server_sock = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)),
-                                        certfile=certificate_file,
-                                        keyfile=private_key_file,
-                                        server_side=True)
-        self.spawn_server(sock=server_sock, site=wsgi_app)
-
-        sock = eventlet.connect(('localhost', self.port))
-        sock = eventlet.wrap_ssl(sock)
-        sock.write(
-            b'POST /foo HTTP/1.1\r\nHost: localhost\r\n'
-            b'Connection: close\r\nContent-length:3\r\n\r\nabc')
-        result = recvall(sock)
-        assert result.endswith(b'abc')
-
-    @tests.skip_if_no_ssl
-    def test_013_empty_return(self):
-        def wsgi_app(environ, start_response):
-            start_response("200 OK", [])
-            return [b""]
-
-        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-        server_sock = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)),
-                                        certfile=certificate_file,
-                                        keyfile=private_key_file,
-                                        server_side=True)
-        self.spawn_server(sock=server_sock, site=wsgi_app)
-
-        sock = eventlet.connect(('localhost', server_sock.getsockname()[1]))
-        sock = eventlet.wrap_ssl(sock)
-        sock.write(b'GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        result = recvall(sock)
-        assert result[-4:] == b'\r\n\r\n'
-
-    def test_014_chunked_post(self):
-        self.site.application = chunked_post
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write('PUT /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
-                 'Transfer-Encoding: chunked\r\n\r\n'
-                 '2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
-        fd.flush()
-        while True:
-            if fd.readline() == b'\r\n':
-                break
-        response = fd.read()
-        assert response == b'oh hai', 'invalid response %s' % response
-
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write('PUT /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
-                 'Transfer-Encoding: chunked\r\n\r\n'
-                 '2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
-        fd.flush()
-        while True:
-            if fd.readline() == b'\r\n':
-                break
-        response = fd.read()
-        assert response == b'oh hai', 'invalid response %s' % response
-
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write('PUT /c HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
-                 'Transfer-Encoding: chunked\r\n\r\n'
-                 '2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
-        fd.flush()
-        while True:
-            if fd.readline() == b'\r\n':
-                break
-        response = fd.read(8192)
-        assert response == b'oh hai', 'invalid response %s' % response
-
-    def test_015_write(self):
-        self.site.application = use_write
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('wb')
-        fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        result1 = read_http(sock)
-        assert 'content-length' in result1.headers_lower
-
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('wb')
-        fd.write(b'GET /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        result2 = read_http(sock)
-        assert 'transfer-encoding' in result2.headers_lower
-        assert result2.headers_lower['transfer-encoding'] == 'chunked'
-
-    def test_016_repeated_content_length(self):
-        """content-length header was being doubled up if it was set in
-        start_response and could also be inferred from the iterator
-        """
-        def wsgi_app(environ, start_response):
-            start_response('200 OK', [('Content-Length', '7')])
-            return [b'testing']
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line)
-        self.assertEqual(1, len(
-            [l for l in header_lines if l.lower().startswith(b'content-length')]))
-
-    @tests.skip_if_no_ssl
-    def test_017_ssl_zeroreturnerror(self):
-
-        def server(sock, site, log):
-            try:
-                serv = wsgi.Server(sock, sock.getsockname(), site, log)
-                client_socket = sock.accept()
-                serv.process_request(client_socket)
-                return True
-            except Exception:
-                traceback.print_exc()
-                return False
-
-        def wsgi_app(environ, start_response):
-            start_response('200 OK', [])
-            return [environ['wsgi.input'].read()]
-
-        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-
-        sock = eventlet.wrap_ssl(
-            eventlet.listen(('localhost', 0)),
-            certfile=certificate_file, keyfile=private_key_file,
-            server_side=True)
-        server_coro = eventlet.spawn(server, sock, wsgi_app, self.logfile)
-
-        client = eventlet.connect(('localhost', sock.getsockname()[1]))
-        client = eventlet.wrap_ssl(client)
-        client.write(b'X')  # non-empty payload so that SSL handshake occurs
-        greenio.shutdown_safe(client)
-        client.close()
-
-        success = server_coro.wait()
-        assert success
-
-    def test_018_http_10_keepalive(self):
-        # verify that if an http/1.0 client sends connection: keep-alive
-        # that we don't close the connection
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
-        fd.flush()
-
-        result1 = read_http(sock)
-        assert 'connection' in result1.headers_lower
-        self.assertEqual('keep-alive', result1.headers_lower['connection'])
-        # repeat request to verify connection is actually still open
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
-        fd.flush()
-        result2 = read_http(sock)
-        assert 'connection' in result2.headers_lower
-        self.assertEqual('keep-alive', result2.headers_lower['connection'])
-        sock.close()
-
-    def test_019_fieldstorage_compat(self):
-        def use_fieldstorage(environ, start_response):
-            cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
-            start_response('200 OK', [('Content-type', 'text/plain')])
-            return [b'hello!']
-
-        self.site.application = use_fieldstorage
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write('POST / HTTP/1.1\r\n'
-                 'Host: localhost\r\n'
-                 'Connection: close\r\n'
-                 'Transfer-Encoding: chunked\r\n\r\n'
-                 '2\r\noh\r\n'
-                 '4\r\n hai\r\n0\r\n\r\n'.encode())
-        fd.flush()
-        assert b'hello!' in fd.read()
-
-    def test_020_x_forwarded_for(self):
-        request_bytes = (
-            b'GET / HTTP/1.1\r\nHost: localhost\r\n'
-            + b'X-Forwarded-For: 1.2.3.4, 5.6.7.8\r\n\r\n'
-        )
-
-        sock = eventlet.connect(('localhost', self.port))
-        sock.sendall(request_bytes)
-        sock.recv(1024)
-        sock.close()
-        assert '1.2.3.4,5.6.7.8,127.0.0.1' in self.logfile.getvalue()
-
-        # turning off the option should work too
-        self.logfile = six.StringIO()
-        self.spawn_server(log_x_forwarded_for=False)
-
-        sock = eventlet.connect(('localhost', self.port))
-        sock.sendall(request_bytes)
-        sock.recv(1024)
-        sock.close()
-        assert '1.2.3.4' not in self.logfile.getvalue()
-        assert '5.6.7.8' not in self.logfile.getvalue()
-        assert '127.0.0.1' in self.logfile.getvalue()
-
-    def test_socket_remains_open(self):
-        greenthread.kill(self.killer)
-        server_sock = eventlet.listen(('localhost', 0))
-        server_sock_2 = server_sock.dup()
-        self.spawn_server(sock=server_sock_2)
-        # do a single req/response to verify it's up
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result = fd.read(1024)
-        fd.close()
-        assert result.startswith(b'HTTP'), result
-        assert result.endswith(b'hello world'), result
-
-        # shut down the server and verify the server_socket fd is still open,
-        # but the actual socketobject passed in to wsgi.server is closed
-        greenthread.kill(self.killer)
-        eventlet.sleep(0)  # make the kill go through
-        try:
-            server_sock_2.accept()
-            # shouldn't be able to use this one anymore
-        except socket.error as exc:
-            self.assertEqual(support.get_errno(exc), errno.EBADF)
-        self.spawn_server(sock=server_sock)
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result = fd.read(1024)
-        fd.close()
-        assert result.startswith(b'HTTP'), result
-        assert result.endswith(b'hello world'), result
-
-    def test_021_environ_clobbering(self):
-        def clobberin_time(environ, start_response):
-            for environ_var in [
-                    'wsgi.version', 'wsgi.url_scheme',
-                    'wsgi.input', 'wsgi.errors', 'wsgi.multithread',
-                    'wsgi.multiprocess', 'wsgi.run_once', 'REQUEST_METHOD',
-                    'SCRIPT_NAME', 'RAW_PATH_INFO', 'PATH_INFO', 'QUERY_STRING',
-                    'CONTENT_TYPE', 'CONTENT_LENGTH', 'SERVER_NAME', 'SERVER_PORT',
-                    'SERVER_PROTOCOL']:
-                environ[environ_var] = None
-            start_response('200 OK', [('Content-type', 'text/plain')])
-            return []
-        self.site.application = clobberin_time
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write('GET / HTTP/1.1\r\n'
-                 'Host: localhost\r\n'
-                 'Connection: close\r\n'
-                 '\r\n\r\n'.encode())
-        fd.flush()
-        assert b'200 OK' in fd.read()
-
-    def test_022_custom_pool(self):
-        # just test that it accepts the parameter for now
-        # TODO(waitall): test that it uses the pool and that you can waitall() to
-        # ensure that all clients finished
-        p = eventlet.GreenPool(5)
-        self.spawn_server(custom_pool=p)
-
-        # this stuff is copied from test_001_server, could be better factored
-        sock = eventlet.connect(
-            ('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result = fd.read()
-        fd.close()
-        assert result.startswith(b'HTTP'), result
-        assert result.endswith(b'hello world'), result
-
-    def test_023_bad_content_length(self):
-        sock = eventlet.connect(
-            ('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nContent-length: argh\r\n\r\n')
-        fd.flush()
-        result = fd.read()
-        fd.close()
-        assert result.startswith(b'HTTP'), result
-        assert b'400 Bad Request' in result, result
-        assert b'500' not in result, result
-
-    def test_024_expect_100_continue(self):
-        def wsgi_app(environ, start_response):
-            if int(environ['CONTENT_LENGTH']) > 1024:
-                start_response('417 Expectation Failed', [('Content-Length', '7')])
-                return [b'failure']
-            else:
-                text = environ['wsgi.input'].read()
-                start_response('200 OK', [('Content-Length', str(len(text)))])
-                return [text]
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\n'
-                 b'Expect: 100-continue\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 417 Expectation Failed')
-        self.assertEqual(result.body, b'failure')
-        fd.write(
-            b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\n'
-            b'Expect: 100-continue\r\n\r\ntesting')
-        fd.flush()
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line)
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line)
-        assert header_lines[0].startswith(b'HTTP/1.1 200 OK')
-        assert fd.read(7) == b'testing'
-        fd.close()
-        sock.close()
-
-    def test_024a_expect_100_continue_with_headers(self):
-        def wsgi_app(environ, start_response):
-            if int(environ['CONTENT_LENGTH']) > 1024:
-                start_response('417 Expectation Failed', [('Content-Length', '7')])
-                return [b'failure']
-            else:
-                environ['wsgi.input'].set_hundred_continue_response_headers(
-                    [('Hundred-Continue-Header-1', 'H1'),
-                     ('Hundred-Continue-Header-2', 'H2'),
-                     ('Hundred-Continue-Header-k', 'Hk')])
-                text = environ['wsgi.input'].read()
-                start_response('200 OK', [('Content-Length', str(len(text)))])
-                return [text]
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\n'
-                 b'Expect: 100-continue\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 417 Expectation Failed')
-        self.assertEqual(result.body, b'failure')
-        fd.write(
-            b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\n'
-            b'Expect: 100-continue\r\n\r\ntesting')
-        fd.flush()
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        headers = dict((k, v) for k, v in (h.split(b': ', 1) for h in header_lines[1:]))
-        assert b'Hundred-Continue-Header-1' in headers
-        assert b'Hundred-Continue-Header-2' in headers
-        assert b'Hundred-Continue-Header-K' in headers
-        self.assertEqual(b'H1', headers[b'Hundred-Continue-Header-1'])
-        self.assertEqual(b'H2', headers[b'Hundred-Continue-Header-2'])
-        self.assertEqual(b'Hk', headers[b'Hundred-Continue-Header-K'])
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line)
-        assert header_lines[0].startswith(b'HTTP/1.1 200 OK')
-        self.assertEqual(fd.read(7), b'testing')
-        fd.close()
-        sock.close()
-
-    def test_024b_expect_100_continue_with_headers_multiple_chunked(self):
-        def wsgi_app(environ, start_response):
-            environ['wsgi.input'].set_hundred_continue_response_headers(
-                [('Hundred-Continue-Header-1', 'H1'),
-                 ('Hundred-Continue-Header-2', 'H2')])
-            text = environ['wsgi.input'].read()
-
-            environ['wsgi.input'].set_hundred_continue_response_headers(
-                [('Hundred-Continue-Header-3', 'H3')])
-            environ['wsgi.input'].send_hundred_continue_response()
-
-            text += environ['wsgi.input'].read()
-
-            start_response('200 OK', [('Content-Length', str(len(text)))])
-            return [text]
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'PUT /a HTTP/1.1\r\n'
-                 b'Host: localhost\r\nConnection: close\r\n'
-                 b'Transfer-Encoding: chunked\r\n'
-                 b'Expect: 100-continue\r\n\r\n')
-        fd.flush()
-
-        # Expect 1st 100-continue response
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        headers = dict((k, v) for k, v in (h.split(b': ', 1)
-                                           for h in header_lines[1:]))
-        assert b'Hundred-Continue-Header-1' in headers
-        assert b'Hundred-Continue-Header-2' in headers
-        self.assertEqual(b'H1', headers[b'Hundred-Continue-Header-1'])
-        self.assertEqual(b'H2', headers[b'Hundred-Continue-Header-2'])
-
-        # Send message 1
-        fd.write(b'5\r\nfirst\r\n8\r\n message\r\n0\r\n\r\n')
-        fd.flush()
-
-        # Expect a 2nd 100-continue response
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        headers = dict((k, v) for k, v in (h.split(b': ', 1)
-                                           for h in header_lines[1:]))
-        assert b'Hundred-Continue-Header-3' in headers
-        self.assertEqual(b'H3', headers[b'Hundred-Continue-Header-3'])
-
-        # Send message 2
-        fd.write(b'8\r\n, second\r\n8\r\n message\r\n0\r\n\r\n')
-        fd.flush()
-
-        # Expect final 200-OK
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 200 OK')
-
-        self.assertEqual(fd.read(29), b'first message, second message')
-        fd.close()
-        sock.close()
-
-    def test_024c_expect_100_continue_with_headers_multiple_nonchunked(self):
-        def wsgi_app(environ, start_response):
-
-            environ['wsgi.input'].set_hundred_continue_response_headers(
-                [('Hundred-Continue-Header-1', 'H1'),
-                 ('Hundred-Continue-Header-2', 'H2')])
-            text = environ['wsgi.input'].read(13)
-
-            environ['wsgi.input'].set_hundred_continue_response_headers(
-                [('Hundred-Continue-Header-3', 'H3')])
-            environ['wsgi.input'].send_hundred_continue_response()
-
-            text += environ['wsgi.input'].read(16)
-
-            start_response('200 OK', [('Content-Length', str(len(text)))])
-            return [text]
-
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'PUT /a HTTP/1.1\r\n'
-                 b'Host: localhost\r\nConnection: close\r\n'
-                 b'Content-Length: 29\r\n'
-                 b'Expect: 100-continue\r\n\r\n')
-        fd.flush()
-
-        # Expect 1st 100-continue response
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        headers = dict((k, v) for k, v in (h.split(b': ', 1)
-                                           for h in header_lines[1:]))
-        assert b'Hundred-Continue-Header-1' in headers
-        assert b'Hundred-Continue-Header-2' in headers
-        self.assertEqual(b'H1', headers[b'Hundred-Continue-Header-1'])
-        self.assertEqual(b'H2', headers[b'Hundred-Continue-Header-2'])
-
-        # Send message 1
-        fd.write(b'first message')
-        fd.flush()
-
-        # Expect a 2nd 100-continue response
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
-        headers = dict((k, v) for k, v in (h.split(b': ', 1)
-                                           for h in header_lines[1:]))
-        assert b'Hundred-Continue-Header-3' in headers
-        self.assertEqual(b'H3', headers[b'Hundred-Continue-Header-3'])
-
-        # Send message 2
-        fd.write(b', second message\r\n')
-        fd.flush()
-
-        # Expect final 200-OK
-        header_lines = []
-        while True:
-            line = fd.readline()
-            if line == b'\r\n':
-                break
-            else:
-                header_lines.append(line.strip())
-        assert header_lines[0].startswith(b'HTTP/1.1 200 OK')
-
-        self.assertEqual(fd.read(29), b'first message, second message')
-        fd.close()
-        sock.close()
-
-    def test_025_accept_errors(self):
-        debug.hub_exceptions(True)
-        listener = greensocket.socket()
-        listener.bind(('localhost', 0))
-        # NOT calling listen, to trigger the error
-        with capture_stderr() as log:
-            self.spawn_server(sock=listener)
-            eventlet.sleep(0)  # need to enter server loop
-            try:
-                eventlet.connect(('localhost', self.port))
-                self.fail("Didn't expect to connect")
-            except socket.error as exc:
-                self.assertEqual(support.get_errno(exc), errno.ECONNREFUSED)
-
-        log_content = log.getvalue()
-        assert 'Invalid argument' in log_content, log_content
-        debug.hub_exceptions(False)
-
-    def test_026_log_format(self):
-        self.spawn_server(log_format="HI %(request_line)s HI")
-        sock = eventlet.connect(('localhost', self.port))
-        sock.sendall(b'GET /yo! HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        sock.recv(1024)
-        sock.close()
-        assert '\nHI GET /yo! HTTP/1.1 HI\n' in self.logfile.getvalue(), self.logfile.getvalue()
-
-    def test_close_chunked_with_1_0_client(self):
-        # verify that if we return a generator from our app
-        # and we're not speaking with a 1.1 client, that we
-        # close the connection
-        self.site.application = chunked_app
-        sock = eventlet.connect(('localhost', self.port))
-
-        sock.sendall(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
-
-        result = read_http(sock)
-        self.assertEqual(result.headers_lower['connection'], 'close')
-        self.assertNotEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
-        self.assertEqual(result.body, b"thisischunked")
-
-    def test_minimum_chunk_size_parameter_leaves_httpprotocol_class_member_intact(self):
-        start_size = wsgi.HttpProtocol.minimum_chunk_size
-
-        self.spawn_server(minimum_chunk_size=start_size * 2)
-        sock = eventlet.connect(('localhost', self.port))
-        sock.sendall(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        read_http(sock)
-
-        self.assertEqual(wsgi.HttpProtocol.minimum_chunk_size, start_size)
-        sock.close()
-
-    def test_error_in_chunked_closes_connection(self):
-        # From http://rhodesmill.org/brandon/2013/chunked-wsgi/
-        self.spawn_server(minimum_chunk_size=1)
-
-        self.site.application = chunked_fail_app
-        sock = eventlet.connect(('localhost', self.port))
-
-        sock.sendall(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 200 OK')
-        self.assertEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
-        expected_body = (
-            b'27\r\nThe dwarves of yore made mighty spells,\r\n'
-            b'25\r\nWhile hammers fell like ringing bells\r\n')
-        self.assertEqual(result.body, expected_body)
-
-        # verify that socket is closed by server
-        self.assertEqual(sock.recv(1), b'')
-
-    def test_026_http_10_nokeepalive(self):
-        # verify that if an http/1.0 client sends connection: keep-alive
-        # and the server doesn't accept keep-alives, we close the connection
-        self.spawn_server(keepalive=False)
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        sock.sendall(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
-        result = read_http(sock)
-        self.assertEqual(result.headers_lower['connection'], 'close')
-
-    def test_027_keepalive_chunked(self):
-        self.site.application = chunked_post
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('wb')
-        common_suffix = (
-            b'Host: localhost\r\nTransfer-Encoding: chunked\r\n\r\n' +
-            b'10\r\n0123456789abcdef\r\n0\r\n\r\n')
-        fd.write(b'PUT /a HTTP/1.1\r\n' + common_suffix)
-        fd.flush()
-        read_http(sock)
-        fd.write(b'PUT /b HTTP/1.1\r\n' + common_suffix)
-        fd.flush()
-        read_http(sock)
-        fd.write(b'PUT /c HTTP/1.1\r\n' + common_suffix)
-        fd.flush()
-        read_http(sock)
-        fd.write(b'PUT /a HTTP/1.1\r\n' + common_suffix)
-        fd.flush()
-        read_http(sock)
-        sock.close()
-
-    @tests.skip_if_no_ssl
-    def test_028_ssl_handshake_errors(self):
-        errored = [False]
-
-        def server(sock):
-            try:
-                wsgi.server(sock=sock, site=hello_world, log=self.logfile)
-                errored[0] = 'SSL handshake error caused wsgi.server to exit.'
-            except greenthread.greenlet.GreenletExit:
-                pass
-            except Exception as e:
-                errored[0] = 'SSL handshake error raised exception %s.' % e
-                raise
-        for data in ('', 'GET /non-ssl-request HTTP/1.0\r\n\r\n'):
-            srv_sock = eventlet.wrap_ssl(
-                eventlet.listen(('localhost', 0)),
-                certfile=certificate_file, keyfile=private_key_file,
-                server_side=True)
-            port = srv_sock.getsockname()[1]
-            g = eventlet.spawn_n(server, srv_sock)
-            client = eventlet.connect(('localhost', port))
-            if data:  # send non-ssl request
-                client.sendall(data.encode())
-            else:  # close sock prematurely
-                client.close()
-            eventlet.sleep(0)  # let context switch back to server
-            assert not errored[0], errored[0]
-            # make another request to ensure the server's still alive
-            try:
-                client = ssl.wrap_socket(eventlet.connect(('localhost', port)))
-                client.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
-                result = recvall(client)
-                assert result.startswith(b'HTTP'), result
-                assert result.endswith(b'hello world')
-            except ImportError:
-                pass  # TODO(openssl): should test with OpenSSL
-            greenthread.kill(g)
-
-    def test_029_posthooks(self):
-        posthook1_count = [0]
-        posthook2_count = [0]
-
-        def posthook1(env, value, multiplier=1):
-            self.assertEqual(env['local.test'], 'test_029_posthooks')
-            posthook1_count[0] += value * multiplier
-
-        def posthook2(env, value, divisor=1):
-            self.assertEqual(env['local.test'], 'test_029_posthooks')
-            posthook2_count[0] += value / divisor
-
-        def one_posthook_app(env, start_response):
-            env['local.test'] = 'test_029_posthooks'
-            if 'eventlet.posthooks' not in env:
-                start_response('500 eventlet.posthooks not supported',
-                               [('Content-Type', 'text/plain')])
-            else:
-                env['eventlet.posthooks'].append(
-                    (posthook1, (2,), {'multiplier': 3}))
-                start_response('200 OK', [('Content-Type', 'text/plain')])
-            yield b''
-        self.site.application = one_posthook_app
-        sock = eventlet.connect(('localhost', self.port))
-        fp = sock.makefile('rwb')
-        fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fp.flush()
-        self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
-        fp.close()
-        sock.close()
-        self.assertEqual(posthook1_count[0], 6)
-        self.assertEqual(posthook2_count[0], 0)
-
-        def two_posthook_app(env, start_response):
-            env['local.test'] = 'test_029_posthooks'
-            if 'eventlet.posthooks' not in env:
-                start_response('500 eventlet.posthooks not supported',
-                               [('Content-Type', 'text/plain')])
-            else:
-                env['eventlet.posthooks'].append(
-                    (posthook1, (4,), {'multiplier': 5}))
-                env['eventlet.posthooks'].append(
-                    (posthook2, (100,), {'divisor': 4}))
-                start_response('200 OK', [('Content-Type', 'text/plain')])
-            yield b''
-        self.site.application = two_posthook_app
-        sock = eventlet.connect(('localhost', self.port))
-        fp = sock.makefile('rwb')
-        fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fp.flush()
-        self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
-        fp.close()
-        sock.close()
-        self.assertEqual(posthook1_count[0], 26)
-        self.assertEqual(posthook2_count[0], 25)
-
-    def test_030_reject_long_header_lines(self):
-        sock = eventlet.connect(('localhost', self.port))
-        request = 'GET / HTTP/1.0\r\nHost: localhost\r\nLong: %s\r\n\r\n' % \
-            ('a' * 10000)
-        send_expect_close(sock, request.encode())
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.0 400 Header Line Too Long')
-
-    def test_031_reject_large_headers(self):
-        sock = eventlet.connect(('localhost', self.port))
-        headers = ('Name: %s\r\n' % ('a' * 7000,)) * 20
-        request = 'GET / HTTP/1.0\r\nHost: localhost\r\n%s\r\n\r\n' % headers
-        send_expect_close(sock, request.encode())
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.0 400 Headers Too Large')
-
-    def test_032_wsgi_input_as_iterable(self):
-        # https://bitbucket.org/eventlet/eventlet/issue/150
-        # env['wsgi.input'] returns a single byte at a time
-        # when used as an iterator
-        g = [0]
-
-        def echo_by_iterating(env, start_response):
-            start_response('200 OK', [('Content-type', 'text/plain')])
-            for chunk in env['wsgi.input']:
-                g[0] += 1
-                yield chunk
-
-        self.site.application = echo_by_iterating
-        upload_data = b'123456789abcdef' * 100
-        request = (
-            'POST / HTTP/1.0\r\n'
-            'Host: localhost\r\n'
-            'Content-Length: %i\r\n\r\n%s'
-        ) % (len(upload_data), bytes_to_str(upload_data))
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(request.encode())
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.body, upload_data)
-        fd.close()
-        self.assertEqual(g[0], 1)
-
-    def test_zero_length_chunked_response(self):
-        def zero_chunked_app(env, start_response):
-            start_response('200 OK', [('Content-type', 'text/plain')])
-            yield b""
-
-        self.site.application = zero_chunked_app
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        response = fd.read().split(b'\r\n')
-        headers = []
-        while True:
-            h = response.pop(0)
-            headers.append(h)
-            if h == b'':
-                break
-        assert b'Transfer-Encoding: chunked' in b''.join(headers), headers
-        # should only be one chunk of zero size with two blank lines
-        # (one terminates the chunk, one terminates the body)
-        self.assertEqual(response, [b'0', b'', b''])
-
-    def test_configurable_url_length_limit(self):
-        self.spawn_server(url_length_limit=20000)
-        sock = eventlet.connect(
-            ('localhost', self.port))
-        path = 'x' * 15000
-        request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
-        fd = sock.makefile('rwb')
-        fd.write(request.encode())
-        fd.flush()
-        result = fd.readline()
-        if result:
-            # windows closes the socket before the data is flushed,
-            # so we never get anything back
-            status = result.split(b' ')[1]
-            self.assertEqual(status, b'200')
-        fd.close()
-
-    def test_aborted_chunked_post(self):
-        read_content = event.Event()
-        blew_up = [False]
-
-        def chunk_reader(env, start_response):
-            try:
-                content = env['wsgi.input'].read(1024)
-            except IOError:
-                blew_up[0] = True
-                content = b'ok'
-            read_content.send(content)
-            start_response('200 OK', [('Content-Type', 'text/plain')])
-            return [content]
-        self.site.application = chunk_reader
-        expected_body = 'a bunch of stuff'
-        data = "\r\n".join(['PUT /somefile HTTP/1.0',
-                            'Transfer-Encoding: chunked',
-                            '',
-                            'def',
-                            expected_body])
-        # start PUT-ing some chunked data but close prematurely
-        sock = eventlet.connect(('127.0.0.1', self.port))
-        sock.sendall(data.encode())
-        sock.close()
-        # the test passes if we successfully get here, and read all the data
-        # in spite of the early close
-        self.assertEqual(read_content.wait(), b'ok')
-        assert blew_up[0]
-
-    def test_exceptions_close_connection(self):
-        def wsgi_app(environ, start_response):
-            raise RuntimeError("intentional error")
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 500 Internal Server Error')
-        self.assertEqual(result.headers_lower['connection'], 'close')
-        assert 'transfer-encoding' not in result.headers_lower
-
-    def test_unicode_raises_error(self):
-        def wsgi_app(environ, start_response):
-            start_response("200 OK", [])
-            yield u"oh hai"
-            yield u"non-encodable unicode: \u0230"
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 500 Internal Server Error')
-        self.assertEqual(result.headers_lower['connection'], 'close')
-        assert b'unicode' in result.body
-
-    def test_path_info_decoding(self):
-        def wsgi_app(environ, start_response):
-            start_response("200 OK", [])
-            yield six.b("decoded: %s" % environ['PATH_INFO'])
-            yield six.b("raw: %s" % environ['RAW_PATH_INFO'])
-        self.site.application = wsgi_app
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('rwb')
-        fd.write(b'GET /a*b@%40%233 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 200 OK')
-        assert b'decoded: /a*b@@#3' in result.body
-        assert b'raw: /a*b@%40%233' in result.body
-
-    def test_ipv6(self):
-        try:
-            sock = eventlet.listen(('::1', 0), family=socket.AF_INET6)
-        except (socket.gaierror, socket.error):  # probably no ipv6
-            return
-        log = six.StringIO()
-        # first thing the server does is try to log the IP it's bound to
-
-        def run_server():
-            try:
-                wsgi.server(sock=sock, log=log, site=Site())
-            except ValueError:
-                log.write(b'broken')
-
-        self.spawn_thread(run_server)
-
-        logval = log.getvalue()
-        while not logval:
-            eventlet.sleep(0.0)
-            logval = log.getvalue()
-        if 'broked' in logval:
-            self.fail('WSGI server raised exception with ipv6 socket')
-
-    def test_debug(self):
-        self.spawn_server(debug=False)
-
-        def crasher(env, start_response):
-            raise RuntimeError("intentional crash")
-        self.site.application = crasher
-
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result1 = read_http(sock)
-        self.assertEqual(result1.status, 'HTTP/1.1 500 Internal Server Error')
-        self.assertEqual(result1.body, b'')
-        self.assertEqual(result1.headers_lower['connection'], 'close')
-        assert 'transfer-encoding' not in result1.headers_lower
-
-        # verify traceback when debugging enabled
-        self.spawn_server(debug=True)
-        self.site.application = crasher
-        sock = eventlet.connect(('localhost', self.port))
-        fd = sock.makefile('wb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        fd.flush()
-        result2 = read_http(sock)
-        self.assertEqual(result2.status, 'HTTP/1.1 500 Internal Server Error')
-        assert b'intentional crash' in result2.body, result2.body
-        assert b'RuntimeError' in result2.body, result2.body
-        assert b'Traceback' in result2.body, result2.body
-        self.assertEqual(result2.headers_lower['connection'], 'close')
-        assert 'transfer-encoding' not in result2.headers_lower
-
-    def test_client_disconnect(self):
-        """Issue #95 Server must handle disconnect from client in the middle of response
-        """
-        def long_response(environ, start_response):
-            start_response('200 OK', [('Content-Length', '9876')])
-            yield b'a' * 9876
-
-        server_sock = eventlet.listen(('localhost', 0))
-        self.port = server_sock.getsockname()[1]
-        server = wsgi.Server(server_sock, server_sock.getsockname(), long_response,
-                             log=self.logfile)
-
-        def make_request():
-            sock = eventlet.connect(server_sock.getsockname())
-            sock.send(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-            sock.close()
-
-        request_thread = eventlet.spawn(make_request)
-        server_conn = server_sock.accept()
-        # Next line must not raise IOError -32 Broken pipe
-        server.process_request(server_conn)
-        request_thread.wait()
-        server_sock.close()
-
-    def test_server_connection_timeout_exception(self):
-        # Handle connection socket timeouts
-        # https://bitbucket.org/eventlet/eventlet/issue/143/
-        # Runs tests.wsgi_test_conntimeout in a separate process.
-        testcode_path = os.path.join(
-            os.path.dirname(os.path.abspath(__file__)),
-            'wsgi_test_conntimeout.py')
-        output = tests.run_python(testcode_path)
-        sections = output.split(b"SEPERATOR_SENTINEL")
-        # first section is empty
-        self.assertEqual(3, len(sections), output)
-        # if the "BOOM" check fails, it's because our timeout didn't happen
-        # (if eventlet stops using file.readline() to read HTTP headers,
-        # for instance)
-        for runlog in sections[1:]:
-            debug = False if "debug set to: False" in runlog else True
-            if debug:
-                self.assertTrue("timed out" in runlog)
-            self.assertTrue("BOOM" in runlog)
-            self.assertFalse("Traceback" in runlog)
-
-    def test_server_socket_timeout(self):
-        self.spawn_server(socket_timeout=0.1)
-        sock = eventlet.connect(('localhost', self.port))
-        sock.send(b'GET / HTTP/1.1\r\n')
-        eventlet.sleep(0.1)
-        try:
-            read_http(sock)
-            assert False, 'Expected ConnectionClosed exception'
-        except ConnectionClosed:
-            pass
-
-    def test_disable_header_name_capitalization(self):
-        # Disable HTTP header name capitalization
-        #
-        # https://github.com/eventlet/eventlet/issues/80
-        random_case_header = ('eTAg', 'TAg-VAluE')
-
-        def wsgi_app(environ, start_response):
-            start_response('200 oK', [random_case_header])
-            return [b'']
-
-        self.spawn_server(site=wsgi_app, capitalize_response_headers=False)
-
-        sock = eventlet.connect(('localhost', self.port))
-        sock.sendall(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        result = read_http(sock)
-        sock.close()
-        self.assertEqual(result.status, 'HTTP/1.1 200 oK')
-        self.assertEqual(result.headers_lower[random_case_header[0].lower()], random_case_header[1])
-        self.assertEqual(result.headers_original[random_case_header[0]], random_case_header[1])
-
-
-def read_headers(sock):
-    fd = sock.makefile('rb')
-    try:
-        response_line = fd.readline()
-    except socket.error as exc:
-        if support.get_errno(exc) == 10053:
-            raise ConnectionClosed
-        raise
-    if not response_line:
-        raise ConnectionClosed
-
-    header_lines = []
-    while True:
-        line = fd.readline()
-        if line == b'\r\n':
-            break
-        else:
-            header_lines.append(line)
-    headers = dict()
-    for x in header_lines:
-        x = x.strip()
-        if not x:
-            continue
-        key, value = x.split(b': ', 1)
-        assert key.lower() not in headers, "%s header duplicated" % key
-        headers[bytes_to_str(key.lower())] = bytes_to_str(value)
-    return bytes_to_str(response_line), headers
-
-
-class IterableAlreadyHandledTest(_TestBase):
-    def set_site(self):
-        self.site = IterableSite()
-
-    def get_app(self):
-        return IterableApp(True)
-
-    def test_iterable_app_keeps_socket_open_unless_connection_close_sent(self):
-        self.site.application = self.get_app()
-        sock = eventlet.connect(
-            ('localhost', self.port))
-
-        fd = sock.makefile('rwb')
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-
-        fd.flush()
-        response_line, headers = read_headers(sock)
-        self.assertEqual(response_line, 'HTTP/1.1 200 OK\r\n')
-        assert 'connection' not in headers
-        fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
-        fd.flush()
-        result = read_http(sock)
-        self.assertEqual(result.status, 'HTTP/1.1 200 OK')
-        self.assertEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
-        self.assertEqual(result.body, b'0\r\n\r\n')  # Still coming back chunked
-
-
-class ProxiedIterableAlreadyHandledTest(IterableAlreadyHandledTest):
-    # same thing as the previous test but ensuring that it works with tpooled
-    # results as well as regular ones
-    @tests.skip_with_pyevent
-    def get_app(self):
-        return tpool.Proxy(super(ProxiedIterableAlreadyHandledTest, self).get_app())
-
-    def tearDown(self):
-        tpool.killall()
-        super(ProxiedIterableAlreadyHandledTest, self).tearDown()
-
-
-class TestChunkedInput(_TestBase):
-    dirt = ""
-    validator = None
-
-    def application(self, env, start_response):
-        input = env['wsgi.input']
-        response = []
-
-        pi = env["PATH_INFO"]
-
-        if pi == "/short-read":
-            d = input.read(10)
-            response = [d]
-        elif pi == "/lines":
-            for x in input:
-                response.append(x)
-        elif pi == "/ping":
-            input.read()
-            response.append(b"pong")
-        elif pi.startswith("/yield_spaces"):
-            if pi.endswith('override_min'):
-                env['eventlet.minimum_write_chunk_size'] = 1
-            self.yield_next_space = False
-
-            def response_iter():
-                yield b' '
-                num_sleeps = 0
-                while not self.yield_next_space and num_sleeps < 200:
-                    eventlet.sleep(.01)
-                    num_sleeps += 1
-
-                yield b' '
-
-            start_response('200 OK',
-                           [('Content-Type', 'text/plain'),
-                            ('Content-Length', '2')])
-            return response_iter()
-        else:
-            raise RuntimeError("bad path")
-
-        start_response('200 OK', [('Content-Type', 'text/plain')])
-        return response
-
-    def connect(self):
-        return eventlet.connect(('localhost', self.port))
-
-    def set_site(self):
-        self.site = Site()
-        self.site.application = self.application
-
-    def chunk_encode(self, chunks, dirt=None):
-        if dirt is None:
-            dirt = self.dirt
-
-        b = ""
-        for c in chunks:
-            b += "%x%s\r\n%s\r\n" % (len(c), dirt, c)
-        return b
-
-    def body(self, dirt=None):
-        return self.chunk_encode(["this", " is ", "chunked", "\nline",
-                                  " 2", "\n", "line3", ""], dirt=dirt)
-
-    def ping(self, fd):
-        fd.sendall(b"GET /ping HTTP/1.1\r\n\r\n")
-        self.assertEqual(read_http(fd).body, b"pong")
-
-    def test_short_read_with_content_length(self):
-        body = self.body()
-        req = "POST /short-read HTTP/1.1\r\ntransfer-encoding: Chunked\r\n" \
-              "Content-Length:1000\r\n\r\n" + body
-
-        fd = self.connect()
-        fd.sendall(req.encode())
-        self.assertEqual(read_http(fd).body, b"this is ch")
-
-        self.ping(fd)
-        fd.close()
-
-    def test_short_read_with_zero_content_length(self):
-        body = self.body()
-        req = "POST /short-read HTTP/1.1\r\ntransfer-encoding: Chunked\r\n" \
-              "Content-Length:0\r\n\r\n" + body
-        fd = self.connect()
-        fd.sendall(req.encode())
-        self.assertEqual(read_http(fd).body, b"this is ch")
-
-        self.ping(fd)
-        fd.close()
-
-    def test_short_read(self):
-        body = self.body()
-        req = "POST /short-read HTTP/1.1\r\ntransfer-encoding: Chunked\r\n\r\n" + body
-
-        fd = self.connect()
-        fd.sendall(req.encode())
-        self.assertEqual(read_http(fd).body, b"this is ch")
-
-        self.ping(fd)
-        fd.close()
-
-    def test_dirt(self):
-        body = self.body(dirt="; here is dirt\0bla")
-        req = "POST /ping HTTP/1.1\r\ntransfer-encoding: Chunked\r\n\r\n" + body
-
-        fd = self.connect()
-        fd.sendall(req.encode())
-        self.assertEqual(read_http(fd).body, b"pong")
-
-        self.ping(fd)
-        fd.close()
-
-    def test_chunked_readline(self):
-        body = self.body()
-        req = "POST /lines HTTP/1.1\r\nContent-Length: %s\r\n" \
-              "transfer-encoding: Chunked\r\n\r\n%s" % (len(body), body)
-
-        fd = self.connect()
-        fd.sendall(req.encode())
-        self.assertEqual(read_http(fd).body, b'this is chunked\nline 2\nline3')
-        fd.close()
-
-    def test_chunked_readline_wsgi_override_minimum_chunk_size(self):
-
-        fd = self.connect()
-        fd.sendall(b"POST /yield_spaces/override_min HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
-
-        resp_so_far = b''
-        with eventlet.Timeout(.1):
-            while True:
-                one_byte = fd.recv(1)
-                resp_so_far += one_byte
-                if resp_so_far.endswith(b'\r\n\r\n'):
-                    break
-            self.assertEqual(fd.recv(1), b' ')
-        try:
-            with eventlet.Timeout(.1):
-                fd.recv(1)
-        except eventlet.Timeout:
-            pass
-        else:
-            assert False
-        self.yield_next_space = True
-
-        with eventlet.Timeout(.1):
-            self.assertEqual(fd.recv(1), b' ')
-
-    def test_chunked_readline_wsgi_not_override_minimum_chunk_size(self):
-
-        fd = self.connect()
-        fd.sendall(b"POST /yield_spaces HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
-
-        resp_so_far = b''
-        try:
-            with eventlet.Timeout(.1):
-                while True:
-                    one_byte = fd.recv(1)
-                    resp_so_far += one_byte
-                    if resp_so_far.endswith(b'\r\n\r\n'):
-                        break
-                self.assertEqual(fd.recv(1), b' ')
-        except eventlet.Timeout:
-            pass
-        else:
-            assert False
-
-    def test_close_before_finished(self):
-        got_signal = []
-
-        def handler(*args):
-            got_signal.append(1)
-            raise KeyboardInterrupt()
-
-        signal.signal(signal.SIGALRM, handler)
-        signal.alarm(1)
-
-        try:
-            body = '4\r\nthi'
-            req = "POST /short-read HTTP/1.1\r\ntransfer-encoding: Chunked\r\n\r\n" + body
-
-            fd = self.connect()
-            fd.sendall(req.encode())
-            fd.close()
-            eventlet.sleep(0.0)
-        finally:
-            signal.alarm(0)
-            signal.signal(signal.SIGALRM, signal.SIG_DFL)
-
-        assert not got_signal, "caught alarm signal. infinite loop detected."
-
-
-if __name__ == '__main__':
-    unittest.main()