Patch 1373 by Adam Hupp.

Fixes intermittent errors in test_xmlrpc due to socket timeouts.
This commit is contained in:
Guido van Rossum 2007-11-02 16:10:06 +00:00
parent 204093ac07
commit 15c974651f
1 changed files with 20 additions and 56 deletions

View File

@ -260,7 +260,6 @@ def http_server(evt, numrequests):
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 http_server(evt, numrequests):
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 @@ class SimpleServerTestCase(unittest.TestCase):
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 @@ class SimpleServerTestCase(unittest.TestCase):
'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 @@ class SimpleServerTestCase(unittest.TestCase):
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 @@ class SimpleServerTestCase(unittest.TestCase):
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 @@ class SimpleServerTestCase(unittest.TestCase):
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 @@ class FailingServerTestCase(unittest.TestCase):
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 @@ class FailingServerTestCase(unittest.TestCase):
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 @@ class FailingServerTestCase(unittest.TestCase):
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')