Allow instantiation of FunctionTimedOut with empty arguments (to support some patterns in unit testing / mocking). Will replace function name with "Unknown Function" if not provided, and timedOutAfter will be "Unknown" or a float of how long until timeout occurred.

This commit is contained in:
Tim Savannah 2019-08-19 17:28:33 -04:00
parent cf8a9545bc
commit af7d6e8a39
2 changed files with 61 additions and 5 deletions

View File

@ -25,6 +25,22 @@ class FunctionTimedOut(BaseException):
def __init__(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None):
'''
__init__ - Create this exception type.
You should not need to do this outside of testing, it will be created by the func_timeout API
@param msg <str> - A predefined message, otherwise we will attempt to generate one from the other arguments.
@param timedOutAfter <None/float> - Number of seconds before timing-out. Filled-in by API, None will produce "Unknown"
@param timedOutFunction <None/function> - Reference to the function that timed-out. Filled-in by API." None will produce "Unknown Function"
@param timedOutArgs <None/tuple/list> - List of fixed-order arguments ( *args ), or None for no args.
@param timedOutKwargs <None/dict> - Dict of keyword arg ( **kwargs ) names to values, or None for no kwargs.
'''
self.timedOutAfter = timedOutAfter
@ -46,7 +62,18 @@ class FunctionTimedOut(BaseException):
@return <str> - Message
'''
return 'Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(self.timedOutFunction.__name__, repr(self.timedOutArgs), repr(self.timedOutKwargs), self.timedOutAfter)
# Try to gather the function name, if available.
# If it is not, default to an "unknown" string to allow default instantiation
if self.timedOutFunction is not None:
timedOutFuncName = self.timedOutFunction.__name__
else:
timedOutFuncName = 'Unknown Function'
if self.timedOutAfter is not None:
timedOutAfterStr = "%f" %(self.timedOutAfter, )
else:
timedOutAfterStr = "Unknown"
return 'Function %s (args=%s) (kwargs=%s) timed out after %s seconds.\n' %(timedOutFuncName, repr(self.timedOutArgs), repr(self.timedOutKwargs), timedOutAfterStr)
def retry(self, timeout=RETRY_SAME_TIMEOUT):
'''

View File

@ -122,7 +122,7 @@ class TestBasic(object):
threadsCleanedUp = True
break
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection'
def test_exception(self):
@ -148,10 +148,39 @@ class TestBasic(object):
assert functionTimedOut.timedOutFunction == sleepFunction , 'Expected timedOutFunction to equal sleepFunction'
assert functionTimedOut.timedOutArgs == (5, 19) , 'Expected args to equal (5, 19)'
assert functionTimedOut.timedOutKwargs == {} , 'Expected timedOutKwargs to equal {}'
def test_instantiateExceptionNoArgs(self):
gotException = False
try:
exc = FunctionTimedOut()
msg = str(exc)
msg2 = exc.getMsg()
except Exception as _e:
sys.stderr.write('Got unexpected exception in test_instantiateExceptionNoArgs with no arguments. %s %s\n\n' %(str(type(_e)), str(_e)))
gotException = True
assert gotException is False, 'Expected to be able to create FunctionTimedOut exception without arguments.'
gotException = False
try:
exc = FunctionTimedOut('test')
msg = str(exc)
msg2 = str(exc.getMsg())
except Exception as _e:
sys.stderr.write('Got unexpected exception in test_instantiateExceptionNoArgs with fixed message string. %s %s\n\n' %(str(type(_e)), str(_e)))
gotException = True
assert gotException is False , 'Expected to be able to create a FunctionTimedOut exception with a fixed message.'
# Other forms (providing the function name) are tested elsewhere.
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())