summaryrefslogtreecommitdiff
path: root/tests/wsgi_test.py
diff options
context:
space:
mode:
authorJakub Stasiak <jakub@stasiak.at>2016-02-09 02:24:47 +0100
committerJakub Stasiak <jakub@stasiak.at>2016-02-09 03:17:18 +0100
commitf011f783db1d9d58ee198dbef35fef9f9d4a6248 (patch)
treeccf61f625ed2900f8071a6abad397db057b6c7ca /tests/wsgi_test.py
parent8a4a1212b2097c6ecca96c81dc355388583ac45d (diff)
downloadeventlet-writelines-fix.tar.gz
wsgi: Fix handling partial writeswritelines-fix
Closes https://github.com/eventlet/eventlet/issues/295
Diffstat (limited to 'tests/wsgi_test.py')
-rw-r--r--tests/wsgi_test.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py
index 50091eb..2c25553 100644
--- a/tests/wsgi_test.py
+++ b/tests/wsgi_test.py
@@ -10,6 +10,8 @@ import tempfile
import traceback
import unittest
+from nose.tools import eq_
+
import eventlet
from eventlet import debug
from eventlet import event
@@ -444,6 +446,43 @@ class TestHttpd(_TestBase):
# Require a CRLF to close the message body
self.assertEqual(response, b'\r\n')
+ def test_partial_writes_are_handled(self):
+ # The bug was caused by the default writelines() implementaiton
+ # (used by the wsgi module) which doesn't check if write()
+ # successfully completed sending *all* data therefore data could be
+ # lost and the client could be left hanging forever.
+ #
+ # Eventlet issue: "Python 3: wsgi doesn't handle correctly partial
+ # write of socket send() when using writelines()",
+ # https://github.com/eventlet/eventlet/issues/295
+ #
+ # Related CPython issue: "Raw I/O writelines() broken",
+ # http://bugs.python.org/issue26292
+
+ # Piece of data large enough that we can reasonably expect it to not
+ # be sent in one piece. Is there a reliable way to determine this
+ # number without testing various sizes empirically?
+ data = b'a' * 10 ** 7
+
+ def application(env, start_response):
+ # Sending content-length is important here, otherwise chunked encoding
+ # is chosen
+ start_response('200 OK', [])
+ yield data
+
+ self.site.application = application
+
+ sock = eventlet.connect(('localhost', self.port))
+
+ # HTTP 1.0 is important here, this tells the server to close the socket
+ # after sending the data so that read_http() can safely read until EOF
+ # without hanging forever.
+ sock.sendall(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
+ result = read_http(sock)
+
+ # This would previously fail because part of the data would be lost
+ eq_(len(result.body), len(data))
+
@tests.skip_if_no_ssl
def test_012_ssl_server(self):
def wsgi_app(environ, start_response):