| from pyroute2 import NSPopen | |
| from distutils.spawn import find_executable | |
| import traceback | |
| import distutils.version | |
| import logging, os, sys | |
| if 'PYTHON_TEST_LOGFILE' in os.environ: | |
| logfile=os.environ['PYTHON_TEST_LOGFILE'] | |
| logging.basicConfig(level=logging.ERROR, filename=logfile, filemode='a') | |
| else: | |
| logging.basicConfig(level=logging.ERROR, stream=sys.stderr) | |
| logger = logging.getLogger() | |
| def has_executable(name): | |
| path = find_executable(name) | |
| if path is None: | |
| raise Exception(name + ": command not found") | |
| return path | |
| # This is a decorator that will allow for logging tests, but flagging them as | |
| # "known to fail". These tests legitimately fail and represent actual bugs, but | |
| # as these are already documented the test status can be "green" without these | |
| # tests, similar to catch2's [!mayfail] tag. | |
| # This is done using the existing python unittest concept of an "expected failure", | |
| # but it is only done after the fact, if the test fails or raises an exception. | |
| # It gives all tests a chance to succeed, but if they fail it logs them and | |
| # continues. | |
| def mayFail(message): | |
| def decorator(func): | |
| def wrapper(*args, **kwargs): | |
| res = None | |
| err = None | |
| try: | |
| res = func(*args, **kwargs) | |
| except BaseException as e: | |
| logger.critical("WARNING! Test %s failed, but marked as passed because it is decorated with @mayFail." % | |
| args[0]) | |
| logger.critical("\tThe reason why this mayFail was: %s" % message) | |
| logger.critical("\tThe failure was: \"%s\"" % e) | |
| logger.critical("\tStacktrace: \"%s\"" % traceback.format_exc()) | |
| testcase=args[0] | |
| testcase.TestResult().addExpectedFailure(testcase, e) | |
| err = e | |
| finally: | |
| if err != None: | |
| raise err | |
| else: | |
| return res | |
| return wrapper | |
| return decorator | |
| class NSPopenWithCheck(NSPopen): | |
| """ | |
| A wrapper for NSPopen that additionally checks if the program | |
| to be executed is available from the system path or not. | |
| If found, it proceeds with the usual NSPopen() call. | |
| Otherwise, it raises an exception. | |
| """ | |
| def __init__(self, nsname, *argv, **kwarg): | |
| name = list(argv)[0][0] | |
| has_executable(name) | |
| super(NSPopenWithCheck, self).__init__(nsname, *argv, **kwarg) | |
| def kernel_version_ge(major, minor): | |
| # True if running kernel is >= X.Y | |
| version = distutils.version.LooseVersion(os.uname()[2]).version | |
| if version[0] > major: | |
| return True | |
| if version[0] < major: | |
| return False | |
| if minor and version[1] < minor: | |
| return False | |
| return True |