Handle EPIPE errors during tests when remote end closes connection

Closes #178

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.
This commit is contained in:
Johannes Erdfelt
2014-12-19 14:54:04 -08:00
committed by Sergey Shepelev
parent 99a5869aa0
commit 7b05b3a1ee

View File

@@ -160,6 +160,18 @@ class ConnectionClosed(Exception):
pass 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): def read_http(sock):
fd = sock.makefile('rb') fd = sock.makefile('rb')
try: try:
@@ -336,10 +348,9 @@ class TestHttpd(_TestBase):
for ii in range(3000): for ii in range(3000):
path_parts.append('path') path_parts.append('path')
path = '/'.join(path_parts) path = '/'.join(path_parts)
request = ('GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path).encode() request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
fd = sock.makefile('rwb') send_expect_close(sock, request.encode())
fd.write(request) fd = sock.makefile('rb')
fd.flush()
result = fd.readline() result = fd.readline()
if result: if result:
# windows closes the socket before the data is flushed, # windows closes the socket before the data is flushed,
@@ -1196,23 +1207,17 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(('localhost', self.port)) sock = eventlet.connect(('localhost', self.port))
request = 'GET / HTTP/1.0\r\nHost: localhost\r\nLong: %s\r\n\r\n' % \ request = 'GET / HTTP/1.0\r\nHost: localhost\r\nLong: %s\r\n\r\n' % \
('a' * 10000) ('a' * 10000)
fd = sock.makefile('rwb') send_expect_close(sock, request.encode())
fd.write(request.encode())
fd.flush()
result = read_http(sock) result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.0 400 Header Line Too Long') self.assertEqual(result.status, 'HTTP/1.0 400 Header Line Too Long')
fd.close()
def test_031_reject_large_headers(self): def test_031_reject_large_headers(self):
sock = eventlet.connect(('localhost', self.port)) sock = eventlet.connect(('localhost', self.port))
headers = ('Name: %s\r\n' % ('a' * 7000,)) * 20 headers = ('Name: %s\r\n' % ('a' * 7000,)) * 20
request = 'GET / HTTP/1.0\r\nHost: localhost\r\n%s\r\n\r\n' % headers request = 'GET / HTTP/1.0\r\nHost: localhost\r\n%s\r\n\r\n' % headers
fd = sock.makefile('rwb') send_expect_close(sock, request.encode())
fd.write(request.encode())
fd.flush()
result = read_http(sock) result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.0 400 Headers Too Large') self.assertEqual(result.status, 'HTTP/1.0 400 Headers Too Large')
fd.close()
def test_032_wsgi_input_as_iterable(self): def test_032_wsgi_input_as_iterable(self):
# https://bitbucket.org/eventlet/eventlet/issue/150 # https://bitbucket.org/eventlet/eventlet/issue/150