mirror of
https://github.com/python/cpython
synced 2024-09-05 00:05:39 +00:00
Patch 1373 by Adam Hupp.
Fixes intermittent errors in test_xmlrpc due to socket timeouts.
This commit is contained in:
parent
204093ac07
commit
15c974651f
|
@ -260,7 +260,6 @@ def div(self, x, y):
|
|||
try:
|
||||
serv = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 0),
|
||||
logRequests=False, bind_and_activate=False)
|
||||
serv.socket.settimeout(3)
|
||||
serv.server_bind()
|
||||
global PORT
|
||||
PORT = serv.socket.getsockname()[1]
|
||||
|
@ -284,26 +283,7 @@ def div(self, x, y):
|
|||
evt.set()
|
||||
|
||||
|
||||
def is_unavailable_exception(e):
|
||||
'''Returns True if the given ProtocolError is the product of a server-side
|
||||
exception caused by the 'temporarily unavailable' response sometimes
|
||||
given by operations on non-blocking sockets.'''
|
||||
# sometimes we get a -1 error code and/or empty headers
|
||||
if e.errcode == -1 or e.headers is None:
|
||||
return True
|
||||
|
||||
exc_mess = e.headers.get('X-exception')
|
||||
if exc_mess and 'temporarily unavailable' in exc_mess.lower():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# NOTE: The tests in SimpleServerTestCase will ignore failures caused by
|
||||
# "temporarily unavailable" exceptions raised in SimpleXMLRPCServer. This
|
||||
# condition occurs infrequently on some platforms, frequently on others, and
|
||||
# is apparently caused by using SimpleXMLRPCServer with a non-blocking socket.
|
||||
# If the server class is updated at some point in the future to handle this
|
||||
# situation more gracefully, these tests should be modified appropriately.
|
||||
|
||||
class SimpleServerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -335,10 +315,8 @@ def test_simple1(self):
|
|||
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
|
||||
self.assertEqual(p.pow(6,8), 6**8)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
def test_introspection1(self):
|
||||
try:
|
||||
|
@ -348,10 +326,8 @@ def test_introspection1(self):
|
|||
'system.methodHelp', 'system.methodSignature', 'system.multicall'])
|
||||
self.assertEqual(set(meth), expected_methods)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
def test_introspection2(self):
|
||||
try:
|
||||
|
@ -359,10 +335,8 @@ def test_introspection2(self):
|
|||
divhelp = p.system.methodHelp('div')
|
||||
self.assertEqual(divhelp, 'This is the div function')
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
def test_introspection3(self):
|
||||
# the SimpleXMLRPCServer doesn't support signatures, but
|
||||
|
@ -372,10 +346,8 @@ def test_introspection3(self):
|
|||
divsig = p.system.methodSignature('div')
|
||||
self.assertEqual(divsig, 'signatures not supported')
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
def test_multicall(self):
|
||||
try:
|
||||
|
@ -389,10 +361,8 @@ def test_multicall(self):
|
|||
self.assertEqual(pow_result, 6**8)
|
||||
self.assertEqual(div_result, 127//42)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
|
||||
# This is a contrived way to make a failure occur on the server side
|
||||
|
@ -409,7 +379,7 @@ class FailingServerTestCase(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.evt = threading.Event()
|
||||
# start server thread to handle requests
|
||||
serv_args = (self.evt, 2)
|
||||
serv_args = (self.evt, 1)
|
||||
threading.Thread(target=http_server, args=serv_args).start()
|
||||
|
||||
# wait for port to be assigned to server
|
||||
|
@ -441,10 +411,8 @@ def test_basic(self):
|
|||
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
|
||||
self.assertEqual(p.pow(6,8), 6**8)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
# protocol error; provide additional information in test output
|
||||
self.fail("%s\n%s" % (e, e.headers))
|
||||
|
||||
def test_fail_no_info(self):
|
||||
# use the broken message class
|
||||
|
@ -454,11 +422,9 @@ def test_fail_no_info(self):
|
|||
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
|
||||
p.pow(6,8)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# The two server-side error headers shouldn't be sent back in this case
|
||||
self.assertTrue(e.headers.get("X-exception") is None)
|
||||
self.assertTrue(e.headers.get("X-traceback") is None)
|
||||
# The two server-side error headers shouldn't be sent back in this case
|
||||
self.assertTrue(e.headers.get("X-exception") is None)
|
||||
self.assertTrue(e.headers.get("X-traceback") is None)
|
||||
else:
|
||||
self.fail('ProtocolError not raised')
|
||||
|
||||
|
@ -474,12 +440,10 @@ def test_fail_with_info(self):
|
|||
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
|
||||
p.pow(6,8)
|
||||
except xmlrpclib.ProtocolError as e:
|
||||
# ignore failures due to non-blocking socket 'unavailable' errors
|
||||
if not is_unavailable_exception(e):
|
||||
# We should get error info in the response
|
||||
expected_err = "invalid literal for int() with base 10: 'I am broken'"
|
||||
self.assertEqual(e.headers.get("x-exception"), expected_err)
|
||||
self.assertTrue(e.headers.get("x-traceback") is not None)
|
||||
# We should get error info in the response
|
||||
expected_err = "invalid literal for int() with base 10: 'I am broken'"
|
||||
self.assertEqual(e.headers.get("x-exception"), expected_err)
|
||||
self.assertTrue(e.headers.get("x-traceback") is not None)
|
||||
else:
|
||||
self.fail('ProtocolError not raised')
|
||||
|
||||
|
|
Loading…
Reference in a new issue