summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cherrypy/test/helper.py12
-rw-r--r--cherrypy/test/test_states.py20
-rw-r--r--cherrypy/test/webtest.py33
3 files changed, 52 insertions, 13 deletions
diff --git a/cherrypy/test/helper.py b/cherrypy/test/helper.py
index fd8bb914..adc225df 100644
--- a/cherrypy/test/helper.py
+++ b/cherrypy/test/helper.py
@@ -341,12 +341,18 @@ class CPWebCase(webtest.WebCase):
sys.exit()
def getPage(self, url, headers=None, method="GET", body=None,
- protocol=None):
- """Open the url. Return status, headers, body."""
+ protocol=None, raise_subcls=None):
+ """Open the url. Return status, headers, body.
+
+ `raise_subcls` must be a tuple with the exceptions classes
+ or a single exception class that are not going to be considered
+ a socket.error regardless that they were are subclass of a
+ socket.error and therefore not considered for a connection retry.
+ """
if self.script_name:
url = httputil.urljoin(self.script_name, url)
return webtest.WebCase.getPage(self, url, headers, method, body,
- protocol)
+ protocol, raise_subcls)
def skip(self, msg='skipped '):
raise nose.SkipTest(msg)
diff --git a/cherrypy/test/test_states.py b/cherrypy/test/test_states.py
index d86e5cf5..dc6891bc 100644
--- a/cherrypy/test/test_states.py
+++ b/cherrypy/test/test_states.py
@@ -204,9 +204,25 @@ class ServerStateTests(helper.CPWebCase):
# thread will just die without writing a response.
engine.start()
cherrypy.server.start()
-
+ # From python3.5 a new exception is retuned when the connection
+ # ends abruptly:
+ # http.client.RemoteDisconnected
+ # RemoteDisconnected is a subclass of:
+ # (ConnectionResetError, http.client.BadStatusLine)
+ # and ConnectionResetError is an indirect subclass of:
+ # OSError
+ # From python 3.3 an up socket.error is an alias to OSError
+ # following PEP-3151, therefore http.client.RemoteDisconnected
+ # is considered a socket.error.
+ #
+ # raise_subcls specifies the classes that are not going
+ # to be considered as a socket.error for the retries.
+ # Given that RemoteDisconnected is part BadStatusLine
+ # we can use the same call for all py3 versions without
+ # sideffects. python < 3.5 will raise directly BadStatusLine
+ # which is not a subclass for socket.error/OSError.
try:
- self.getPage("/ctrlc")
+ self.getPage("/ctrlc", raise_subcls=BadStatusLine)
except BadStatusLine:
pass
else:
diff --git a/cherrypy/test/webtest.py b/cherrypy/test/webtest.py
index fc3cab49..c9aeb71d 100644
--- a/cherrypy/test/webtest.py
+++ b/cherrypy/test/webtest.py
@@ -238,8 +238,13 @@ class WebCase(TestCase):
return interface(self.HOST)
def getPage(self, url, headers=None, method="GET", body=None,
- protocol=None):
+ protocol=None, raise_subcls=None):
"""Open the url with debugging support. Return status, headers, body.
+
+ `raise_subcls` must be a tuple with the exceptions classes
+ or a single exception class that are not going to be considered
+ a socket.error regardless that they were are subclass of a
+ socket.error and therefore not considered for a connection retry.
"""
ServerError.on = False
@@ -252,7 +257,8 @@ class WebCase(TestCase):
self.time = None
start = time.time()
result = openURL(url, headers, method, body, self.HOST, self.PORT,
- self.HTTP_CONN, protocol or self.PROTOCOL)
+ self.HTTP_CONN, protocol or self.PROTOCOL,
+ raise_subcls)
self.time = time.time() - start
self.status, self.headers, self.body = result
@@ -492,9 +498,15 @@ def shb(response):
def openURL(url, headers=None, method="GET", body=None,
host="127.0.0.1", port=8000, http_conn=HTTPConnection,
- protocol="HTTP/1.1"):
- """Open the given HTTP resource and return status, headers, and body."""
+ protocol="HTTP/1.1", raise_subcls=None):
+ """
+ Open the given HTTP resource and return status, headers, and body.
+ `raise_subcls` must be a tuple with the exceptions classes
+ or a single exception class that are not going to be considered
+ a socket.error regardless that they were are subclass of a
+ socket.error and therefore not considered for a connection retry.
+ """
headers = cleanHeaders(headers, method, body, host, port)
# Trying 10 times is simply in case of socket errors.
@@ -512,7 +524,6 @@ def openURL(url, headers=None, method="GET", body=None,
if py3k and isinstance(url, bytes):
url = url.decode()
-
conn.putrequest(method.upper(), url, skip_host=True,
skip_accept_encoding=True)
@@ -533,10 +544,16 @@ def openURL(url, headers=None, method="GET", body=None,
conn.close()
return s, h, b
- except socket.error:
- time.sleep(0.5)
- if trial == 9:
+ except socket.error as e:
+ if (raise_subcls is not None and
+ issubclass(e.__class__, raise_subcls)):
raise
+ else:
+ time.sleep(0.5)
+ if trial == 9:
+ raise
+
+
# Add any exceptions which your web framework handles