Add socket timeout tests and helpers
Add tests that use a simple socket server instance that opens the port and ignores all data in order to support testing when the socket timeout is set and catching the exception triggered. Also test that when not set that the request will continue to remain connected for a period of time longer than the other test using a wrapper time limit process. Includes some helper classes to black hole all requests by simply listening using a socketserver but never accepting connections, and a time limit function to allow wrapping actions with a time limit when checking for blocking behaviour where the call should not return and will need to be focibly terminated. Change-Id: Idab98b0121adb26aed6320ddcf2afbdf2c4428e0
This commit is contained in:
parent
c83e9b1dc1
commit
0a1b414f3a
@ -181,6 +181,10 @@ class BadHTTPException(JenkinsException):
|
||||
pass
|
||||
|
||||
|
||||
class TimeoutException(JenkinsException):
|
||||
'''A special exception to call out in the case of a socket timeout.'''
|
||||
|
||||
|
||||
def auth_headers(username, password):
|
||||
'''Simple implementation of HTTP Basic Authentication.
|
||||
|
||||
@ -333,7 +337,13 @@ class Jenkins(object):
|
||||
raise NotFoundException('Requested item could not be found')
|
||||
else:
|
||||
raise
|
||||
except socket.timeout as e:
|
||||
raise TimeoutException('Error in request: %s' % (e))
|
||||
except URLError as e:
|
||||
# python 2.6 compatibility to ensure same exception raised
|
||||
# since URLError wraps a socket timeout on python 2.6.
|
||||
if str(e.reason) == "timed out":
|
||||
raise TimeoutException('Error in request: %s' % (e.reason))
|
||||
raise JenkinsException('Error in request: %s' % (e.reason))
|
||||
|
||||
def get_build_info(self, name, number, depth=0):
|
||||
|
@ -1,2 +1,2 @@
|
||||
six
|
||||
six>=1.3.0
|
||||
pbr>=0.8.2,<2.0
|
||||
|
33
tests/helper.py
Normal file
33
tests/helper.py
Normal file
@ -0,0 +1,33 @@
|
||||
from multiprocessing import Process
|
||||
|
||||
from six.moves import socketserver
|
||||
|
||||
|
||||
class TestsTimeoutException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def time_limit(seconds, func, *args, **kwargs):
|
||||
# although creating a separate process is expensive it's the only way to
|
||||
# ensure cross platform that we can cleanly terminate after timeout
|
||||
p = Process(target=func, args=args, kwargs=kwargs)
|
||||
p.start()
|
||||
p.join(seconds)
|
||||
p.terminate()
|
||||
if p.exitcode is None:
|
||||
raise TestsTimeoutException
|
||||
|
||||
|
||||
class NullServer(socketserver.TCPServer):
|
||||
|
||||
request_queue_size = 1
|
||||
|
||||
def __init__(self, server_address, *args, **kwargs):
|
||||
# TCPServer is old style in python 2.x so cannot use
|
||||
# super() correctly, explicitly call __init__.
|
||||
|
||||
# simply init'ing is sufficient to open the port, which
|
||||
# with the server not started creates a black hole server
|
||||
socketserver.TCPServer.__init__(
|
||||
self, server_address, socketserver.BaseRequestHandler,
|
||||
*args, **kwargs)
|
39
tests/test_jenkins_sockets.py
Normal file
39
tests/test_jenkins_sockets.py
Normal file
@ -0,0 +1,39 @@
|
||||
import sys
|
||||
|
||||
import jenkins
|
||||
from tests.helper import NullServer
|
||||
from tests.helper import TestsTimeoutException
|
||||
from tests.helper import time_limit
|
||||
|
||||
if sys.version_info < (2, 7):
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
|
||||
class JenkinsRequestTimeoutTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(JenkinsRequestTimeoutTests, self).setUp()
|
||||
self.server = NullServer(("127.0.0.1", 0))
|
||||
|
||||
def test_jenkins_open_timeout(self):
|
||||
j = jenkins.Jenkins("http://%s:%s" % self.server.server_address,
|
||||
None, None, timeout=0.1)
|
||||
request = jenkins.Request('http://%s:%s/job/TestJob' %
|
||||
self.server.server_address)
|
||||
|
||||
# assert our request times out when no response
|
||||
with self.assertRaises(jenkins.TimeoutException):
|
||||
j.jenkins_open(request, add_crumb=False)
|
||||
|
||||
def test_jenkins_open_no_timeout(self):
|
||||
j = jenkins.Jenkins("http://%s:%s" % self.server.server_address,
|
||||
None, None)
|
||||
request = jenkins.Request('http://%s:%s/job/TestJob' %
|
||||
self.server.server_address)
|
||||
|
||||
# assert we don't timeout quickly like previous test when
|
||||
# no timeout defined.
|
||||
with self.assertRaises(TestsTimeoutException):
|
||||
time_limit(0.5, j.jenkins_open, request, add_crumb=False)
|
Loading…
Reference in New Issue
Block a user