diff options
-rw-r--r-- | cherrypy/test/helper.py | 12 | ||||
-rw-r--r-- | cherrypy/test/test_states.py | 20 | ||||
-rw-r--r-- | cherrypy/test/webtest.py | 33 |
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 |