diff options
Diffstat (limited to 'test/unit')
26 files changed, 338 insertions, 169 deletions
diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 557753a4..93e0738b 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -2,11 +2,11 @@ import os import shutil import subprocess -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationGo(TestApplicationProto): +class ApplicationGo(ApplicationProto): @staticmethod def prepare_env(script, name='app', static=False): try: @@ -88,7 +88,7 @@ replace unit.nginx.org/go => {replace_path} executable = f"/go/{name}" static_build = True - TestApplicationGo.prepare_env(script, name, static=static_build) + ApplicationGo.prepare_env(script, name, static=static_build) conf = { "listeners": {"*:7080": {"pass": f"applications/{script}"}}, diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index b6382cfe..a253aea5 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -4,12 +4,13 @@ import shutil import subprocess import pytest -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationJava(TestApplicationProto): - application_type = "java" +class ApplicationJava(ApplicationProto): + def __init__(self, application_type='java'): + self.application_type = application_type def prepare_env(self, script): app_path = f'{option.temp_dir}/java' @@ -52,7 +53,7 @@ class TestApplicationJava(TestApplicationProto): os.makedirs(classes_path) classpath = ( - f'{option.current_dir}/build/tomcat-servlet-api-9.0.70.jar' + f'{option.current_dir}/build/tomcat-servlet-api-9.0.75.jar' ) ws_jars = glob.glob( diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index 87d5a19c..4f18c780 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,14 +1,15 @@ import shutil from urllib.parse import quote -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option from unit.utils import public_dir -class TestApplicationNode(TestApplicationProto): - application_type = "node" - es_modules = False +class ApplicationNode(ApplicationProto): + def __init__(self, application_type='node', es_modules=False): + self.application_type = application_type + self.es_modules = es_modules def prepare_env(self, script): # copy application diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index 19852363..037e98e8 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -1,9 +1,10 @@ -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationPerl(TestApplicationProto): - application_type = "perl" +class ApplicationPerl(ApplicationProto): + def __init__(self, application_type='perl'): + self.application_type = application_type def load(self, script, name='psgi.pl', **kwargs): script_path = f'{option.test_dir}/perl/{script}' diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index 1b94c3ae..b9b6dbf1 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -1,12 +1,13 @@ import os import shutil -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationPHP(TestApplicationProto): - application_type = "php" +class ApplicationPHP(ApplicationProto): + def __init__(self, application_type='php'): + self.application_type = application_type def load(self, script, index='index.php', **kwargs): script_path = f'{option.test_dir}/php/{script}' diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index 0bb69992..4e1fd897 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -2,13 +2,14 @@ import os import shutil from urllib.parse import quote -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationPython(TestApplicationProto): - application_type = "python" - load_module = "wsgi" +class ApplicationPython(ApplicationProto): + def __init__(self, application_type='python', load_module='wsgi'): + self.application_type = application_type + self.load_module = load_module def load(self, script, name=None, module=None, **kwargs): if name is None: diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index e0712fc6..f6c4f6c3 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -1,12 +1,13 @@ import shutil -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option from unit.utils import public_dir -class TestApplicationRuby(TestApplicationProto): - application_type = "ruby" +class ApplicationRuby(ApplicationProto): + def __init__(self, application_type='ruby'): + self.application_type = application_type def prepare_env(self, script): shutil.copytree( diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index f04ee408..7a1636c6 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -1,41 +1,12 @@ import os -import re -import time -from unit.control import TestControl -from unit.log import Log +from unit.control import Control from unit.option import option -class TestApplicationProto(TestControl): +class ApplicationProto(Control): application_type = None - def sec_epoch(self): - return time.mktime(time.gmtime()) - - def date_to_sec_epoch(self, date, template='%a, %d %b %Y %X %Z'): - return time.mktime(time.strptime(date, template)) - - def findall(self, pattern, name='unit.log', flags=re.M): - with Log.open(name) as f: - return re.findall(pattern, f.read(), flags) - - def search_in_log(self, pattern, name='unit.log', flags=re.M): - with Log.open(name) as f: - return re.search(pattern, f.read(), flags) - - def wait_for_record(self, pattern, name='unit.log', wait=150, flags=re.M): - with Log.open(name) as f: - for i in range(wait): - found = re.search(pattern, f.read(), flags) - - if found is not None: - break - - time.sleep(0.1) - - return found - def get_application_type(self): current_test = ( os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0] diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index e5813312..e9bcc514 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -2,15 +2,15 @@ import os import ssl import subprocess -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto from unit.option import option -class TestApplicationTLS(TestApplicationProto): - def setup_method(self): - self.context = ssl.create_default_context() - self.context.check_hostname = False - self.context.verify_mode = ssl.CERT_NONE +class ApplicationTLS(ApplicationProto): + def __init__(self): + self._default_context = ssl.create_default_context() + self._default_context.check_hostname = False + self._default_context.verify_mode = ssl.CERT_NONE def certificate(self, name='default', load=True): self.openssl_conf() @@ -47,10 +47,12 @@ class TestApplicationTLS(TestApplicationProto): return self.conf(k.read() + c.read(), f'/certificates/{crt}') def get_ssl(self, **kwargs): - return self.get(wrapper=self.context.wrap_socket, **kwargs) + context = kwargs.get('context', self._default_context) + return self.get(wrapper=context.wrap_socket, **kwargs) def post_ssl(self, **kwargs): - return self.post(wrapper=self.context.wrap_socket, **kwargs) + context = kwargs.get('context', self._default_context) + return self.post(wrapper=context.wrap_socket, **kwargs) def openssl_conf(self, rewrite=False, alt_names=None): alt_names = alt_names or [] diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index a4b9287d..29725943 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -6,12 +6,12 @@ import select import struct import pytest -from unit.applications.proto import TestApplicationProto +from unit.applications.proto import ApplicationProto GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" -class TestApplicationWebsocket(TestApplicationProto): +class ApplicationWebsocket(ApplicationProto): OP_CONT = 0x00 OP_TEXT = 0x01 diff --git a/test/unit/check/check_prerequisites.py b/test/unit/check/check_prerequisites.py new file mode 100644 index 00000000..44c3f10f --- /dev/null +++ b/test/unit/check/check_prerequisites.py @@ -0,0 +1,63 @@ +import pytest +from unit.option import option + + +def check_prerequisites(prerequisites): + if 'privileged_user' in prerequisites: + if prerequisites['privileged_user'] and not option.is_privileged: + pytest.skip( + 'privileged user required', + allow_module_level=True, + ) + elif not prerequisites['privileged_user'] and option.is_privileged: + pytest.skip( + 'unprivileged user required', + allow_module_level=True, + ) + + missed = [] + + # check modules + + if 'modules' in prerequisites: + available = option.available['modules'] + + for module in prerequisites['modules']: + if module in available and available[module]: + continue + + missed.append(module) + + if missed: + pytest.skip( + f'Unit has no {", ".join(missed)} module(s)', + allow_module_level=True, + ) + + # check features + + if 'features' in prerequisites: + available = option.available['features'] + require = prerequisites['features'] + + for feature in require: + avail_feature = available[feature] + + if feature in available and avail_feature: + if isinstance(require[feature], list) and isinstance( + avail_feature, dict + ): + avail_keys = avail_feature.keys() + + for key in require[feature]: + if key not in avail_keys: + missed.append(f'{feature}/{key}') + continue + + missed.append(feature) + + if missed: + pytest.skip( + f'{", ".join(missed)} feature(s) not supported', + allow_module_level=True, + ) diff --git a/test/unit/check/chroot.py b/test/unit/check/chroot.py index 1b7aae90..b749fab6 100644 --- a/test/unit/check/chroot.py +++ b/test/unit/check/chroot.py @@ -1,32 +1,30 @@ import json -from unit.http import TestHTTP +from unit.http import HTTP1 from unit.option import option -http = TestHTTP() +http = HTTP1() def check_chroot(): - available = option.available - - resp = http.put( - url='/config', - sock_type='unix', - addr=f'{option.temp_dir}/control.unit.sock', - body=json.dumps( - { - "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [ - { - "action": { - "share": option.temp_dir, - "chroot": option.temp_dir, + return ( + 'success' + in http.put( + url='/config', + sock_type='unix', + addr=f'{option.temp_dir}/control.unit.sock', + body=json.dumps( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [ + { + "action": { + "share": option.temp_dir, + "chroot": option.temp_dir, + } } - } - ], - } - ), + ], + } + ), + )['body'] ) - - if 'success' in resp['body']: - available['features']['chroot'] = True diff --git a/test/unit/check/discover_available.py b/test/unit/check/discover_available.py new file mode 100644 index 00000000..0942581b --- /dev/null +++ b/test/unit/check/discover_available.py @@ -0,0 +1,47 @@ +import subprocess +import sys + +from unit.check.chroot import check_chroot +from unit.check.go import check_go +from unit.check.isolation import check_isolation +from unit.check.njs import check_njs +from unit.check.node import check_node +from unit.check.regex import check_regex +from unit.check.tls import check_openssl +from unit.check.unix_abstract import check_unix_abstract +from unit.log import Log +from unit.option import option + + +def discover_available(unit): + output_version = subprocess.check_output( + [unit['unitd'], '--version'], stderr=subprocess.STDOUT + ).decode() + + # wait for controller start + + if Log.wait_for_record(r'controller started') is None: + Log.print_log() + sys.exit("controller didn't start") + + # discover modules from log file + + for module in Log.findall(r'module: ([a-zA-Z]+) (.*) ".*"$'): + versions = option.available['modules'].setdefault(module[0], []) + if module[1] not in versions: + versions.append(module[1]) + + # discover modules using check + + option.available['modules']['go'] = check_go() + option.available['modules']['njs'] = check_njs(output_version) + option.available['modules']['node'] = check_node() + option.available['modules']['openssl'] = check_openssl(output_version) + option.available['modules']['regex'] = check_regex(output_version) + + # Discover features using check. Features should be discovered after + # modules since some features can require modules. + + option.available['features']['chroot'] = check_chroot() + option.available['features']['isolation'] = check_isolation() + option.available['features']['unix_abstract'] = check_unix_abstract() diff --git a/test/unit/check/go.py b/test/unit/check/go.py index 09ae641d..1ecd429b 100644 --- a/test/unit/check/go.py +++ b/test/unit/check/go.py @@ -1,6 +1,5 @@ -from unit.applications.lang.go import TestApplicationGo +from unit.applications.lang.go import ApplicationGo def check_go(): - if TestApplicationGo.prepare_env('empty') is not None: - return True + return ApplicationGo.prepare_env('empty') is not None diff --git a/test/unit/check/isolation.py b/test/unit/check/isolation.py index 4ebce893..e4674f4d 100644 --- a/test/unit/check/isolation.py +++ b/test/unit/check/isolation.py @@ -1,25 +1,24 @@ import json import os -from unit.applications.lang.go import TestApplicationGo -from unit.applications.lang.java import TestApplicationJava -from unit.applications.lang.node import TestApplicationNode -from unit.applications.lang.ruby import TestApplicationRuby -from unit.http import TestHTTP +from unit.applications.lang.go import ApplicationGo +from unit.applications.lang.java import ApplicationJava +from unit.applications.lang.node import ApplicationNode +from unit.applications.lang.ruby import ApplicationRuby +from unit.http import HTTP1 from unit.option import option from unit.utils import getns allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net'] -http = TestHTTP() +http = HTTP1() def check_isolation(): - test_conf = {"namespaces": {"credential": True}} available = option.available conf = '' if 'go' in available['modules']: - TestApplicationGo().prepare_env('empty', 'app') + ApplicationGo().prepare_env('empty', 'app') conf = { "listeners": {"*:7080": {"pass": "applications/empty"}}, @@ -65,7 +64,7 @@ def check_isolation(): } elif 'ruby' in available['modules']: - TestApplicationRuby().prepare_env('empty') + ApplicationRuby().prepare_env('empty') conf = { "listeners": {"*:7080": {"pass": "applications/empty"}}, @@ -81,7 +80,7 @@ def check_isolation(): } elif 'java' in available['modules']: - TestApplicationJava().prepare_env('empty') + ApplicationJava().prepare_env('empty') conf = { "listeners": {"*:7080": {"pass": "applications/empty"}}, @@ -98,7 +97,7 @@ def check_isolation(): } elif 'node' in available['modules']: - TestApplicationNode().prepare_env('basic') + ApplicationNode().prepare_env('basic') conf = { "listeners": {"*:7080": {"pass": "applications/basic"}}, @@ -128,7 +127,7 @@ def check_isolation(): } else: - return + return False resp = http.put( url='/config', @@ -138,23 +137,23 @@ def check_isolation(): ) if 'success' not in resp['body']: - return + return False userns = getns('user') if not userns: - return + return False - available['features']['isolation'] = {'user': userns} + isolation = {'user': userns} unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone' if os.path.exists(unp_clone_path): with open(unp_clone_path, 'r') as f: if str(f.read()).rstrip() == '1': - available['features']['isolation'][ - 'unprivileged_userns_clone' - ] = True + isolation['unprivileged_userns_clone'] = True for ns in allns: ns_value = getns(ns) if ns_value: - available['features']['isolation'][ns] = ns_value + isolation[ns] = ns_value + + return isolation diff --git a/test/unit/check/njs.py b/test/unit/check/njs.py index 433473a1..363a1b62 100644 --- a/test/unit/check/njs.py +++ b/test/unit/check/njs.py @@ -2,5 +2,4 @@ import re def check_njs(output_version): - if re.search('--njs', output_version): - return True + return re.search('--njs', output_version) diff --git a/test/unit/check/node.py b/test/unit/check/node.py index dd59e7a4..6a3d581f 100644 --- a/test/unit/check/node.py +++ b/test/unit/check/node.py @@ -1,10 +1,12 @@ import os import subprocess +from unit.option import option -def check_node(current_dir): - if not os.path.exists(f'{current_dir}/node/node_modules'): - return None + +def check_node(): + if not os.path.exists(f'{option.current_dir}/node/node_modules'): + return False try: v_bytes = subprocess.check_output(['/usr/bin/env', 'node', '-v']) @@ -12,4 +14,4 @@ def check_node(current_dir): return [str(v_bytes, 'utf-8').lstrip('v').rstrip()] except subprocess.CalledProcessError: - return None + return False diff --git a/test/unit/check/regex.py b/test/unit/check/regex.py index 51cf966b..83e93f2d 100644 --- a/test/unit/check/regex.py +++ b/test/unit/check/regex.py @@ -2,7 +2,4 @@ import re def check_regex(output_version): - if re.search('--no-regex', output_version): - return False - - return True + return not re.search('--no-regex', output_version) diff --git a/test/unit/check/tls.py b/test/unit/check/tls.py index 53ce5ffc..9cc2a5f9 100644 --- a/test/unit/check/tls.py +++ b/test/unit/check/tls.py @@ -6,7 +6,6 @@ def check_openssl(output_version): try: subprocess.check_output(['which', 'openssl']) except subprocess.CalledProcessError: - return None + return False - if re.search('--openssl', output_version): - return True + return re.search('--openssl', output_version) diff --git a/test/unit/check/unix_abstract.py b/test/unit/check/unix_abstract.py index aadde43a..8fc7dd84 100644 --- a/test/unit/check/unix_abstract.py +++ b/test/unit/check/unix_abstract.py @@ -1,25 +1,25 @@ import json -from unit.http import TestHTTP +from unit.http import HTTP1 from unit.option import option -http = TestHTTP() +http = HTTP1() def check_unix_abstract(): - available = option.available - - resp = http.put( - url='/config', - sock_type='unix', - addr=f'{option.temp_dir}/control.unit.sock', - body=json.dumps( - { - "listeners": {"unix:@sock": {"pass": "routes"}}, - "routes": [], - } - ), + return ( + 'success' + in http.put( + url='/config', + sock_type='unix', + addr=f'{option.temp_dir}/control.unit.sock', + body=json.dumps( + { + "listeners": { + f'unix:@{option.temp_dir}/sock': {"pass": "routes"} + }, + "routes": [], + } + ), + )['body'] ) - - if 'success' in resp['body']: - available['features']['unix_abstract'] = True diff --git a/test/unit/control.py b/test/unit/control.py index 61b6edf4..164d0e60 100644 --- a/test/unit/control.py +++ b/test/unit/control.py @@ -1,6 +1,6 @@ import json -from unit.http import TestHTTP +from unit.http import HTTP1 from unit.option import option @@ -29,7 +29,7 @@ def args_handler(conf_func): return args_wrapper -class TestControl(TestHTTP): +class Control(HTTP1): @args_handler def conf(self, conf, url): return self.put(**self._get_args(url, conf))['body'] diff --git a/test/unit/http.py b/test/unit/http.py index 6a267e26..347382f5 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -10,7 +10,7 @@ import pytest from unit.option import option -class TestHTTP: +class HTTP1: def http(self, start_str, **kwargs): sock_type = kwargs.get('sock_type', 'ipv4') port = kwargs.get('port', 7080) diff --git a/test/unit/log.py b/test/unit/log.py index f984d7a1..7d7e355a 100644 --- a/test/unit/log.py +++ b/test/unit/log.py @@ -1,23 +1,113 @@ +import os +import re +import sys +import time + +from unit.option import option + UNIT_LOG = 'unit.log' +def print_log_on_assert(func): + def inner_function(*args, **kwargs): + try: + func(*args, **kwargs) + except AssertionError as exception: + Log.print_log(*args, **kwargs) + raise exception + + return inner_function + + class Log: - temp_dir = None pos = {} - def open(name=UNIT_LOG, encoding=None): - f = open(Log.get_path(name), 'r', encoding=encoding, errors='ignore') - f.seek(Log.pos.get(name, 0)) + @staticmethod + @print_log_on_assert + def check_alerts(log=None): + if log is None: + log = Log.read() + + found = False + alerts = re.findall(r'.+\[alert\].+', log) + + if alerts: + found = True - return f + if option.detailed: + print('\nAll alerts/sanitizer errors found in log:') + _ = [print(alert) for alert in alerts] + if option.skip_alerts: + for skip in option.skip_alerts: + alerts = [al for al in alerts if re.search(skip, al) is None] + + assert not alerts, 'alert(s)' + + if not option.skip_sanitizer: + sanitizer_errors = re.findall('.+Sanitizer.+', log) + + assert not sanitizer_errors, 'sanitizer error(s)' + + if found and option.detailed: + print('skipped.') + + @staticmethod + def findall(pattern, name=UNIT_LOG, flags=re.M): + return re.findall(pattern, Log.read(name), flags) + + @staticmethod + def get_path(name=UNIT_LOG): + return f'{option.temp_dir}/{name}' + + @staticmethod + def open(name=UNIT_LOG, encoding='utf-8'): + file = open(Log.get_path(name), 'r', encoding=encoding, errors='ignore') + file.seek(Log.pos.get(name, 0)) + + return file + + @staticmethod + def print_log(log=None): + Log.print_path() + + if option.print_log: + os.set_blocking(sys.stdout.fileno(), True) + sys.stdout.flush() + + if log is None: + log = Log.read() + + sys.stdout.write(log) + + @staticmethod + def print_path(): + print(f'Path to {UNIT_LOG}:\n{Log.get_path()}\n') + + @staticmethod + def read(*args, **kwargs): + with Log.open(*args, **kwargs) as file: + return file.read() + + @staticmethod def set_pos(pos, name=UNIT_LOG): Log.pos[name] = pos + @staticmethod def swap(name): pos = Log.pos.get(UNIT_LOG, 0) Log.pos[UNIT_LOG] = Log.pos.get(name, 0) Log.pos[name] = pos - def get_path(name=UNIT_LOG): - return f'{Log.temp_dir}/{name}' + @staticmethod + def wait_for_record(pattern, name=UNIT_LOG, wait=150, flags=re.M): + with Log.open(name) as file: + for _ in range(wait): + found = re.search(pattern, file.read(), flags) + + if found is not None: + break + + time.sleep(0.1) + + return found diff --git a/test/unit/option.py b/test/unit/option.py index cb3803dc..ee1f46dd 100644 --- a/test/unit/option.py +++ b/test/unit/option.py @@ -1,7 +1,15 @@ +import os +import platform + + class Options: _options = { + 'architecture': platform.architecture()[0], + 'available': {'modules': {}, 'features': {}}, + 'is_privileged': os.geteuid() == 0, 'skip_alerts': [], 'skip_sanitizer': False, + 'system': platform.system(), } def __setattr__(self, name, value): diff --git a/test/unit/status.py b/test/unit/status.py index 17416f17..84c958a3 100644 --- a/test/unit/status.py +++ b/test/unit/status.py @@ -1,9 +1,9 @@ -from unit.control import TestControl +from unit.control import Control class Status: _status = None - control = TestControl() + control = Control() def _check_zeros(): assert Status.control.conf_get('/status') == { diff --git a/test/unit/utils.py b/test/unit/utils.py index 985801e2..cd823e27 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -24,7 +24,7 @@ def public_dir(path): def waitforfiles(*files, timeout=50): - for i in range(timeout): + for _ in range(timeout): wait = False for f in files: @@ -41,10 +41,10 @@ def waitforfiles(*files, timeout=50): def waitforglob(pattern, count=1, timeout=50): - for i in range(timeout): + for _ in range(timeout): n = 0 - for f in glob.glob(pattern): + for _ in glob.glob(pattern): n += 1 if n == count: @@ -56,7 +56,7 @@ def waitforglob(pattern, count=1, timeout=50): def waitforsocket(port): - for i in range(50): + for _ in range(50): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: try: sock.settimeout(5) @@ -90,19 +90,8 @@ def findmnt(): return out -def sysctl(): - try: - out = subprocess.check_output( - ['sysctl', '-a'], stderr=subprocess.STDOUT - ).decode() - except FileNotFoundError: - pytest.skip('requires sysctl') - - return out - - def waitformount(template, timeout=50): - for i in range(timeout): + for _ in range(timeout): if findmnt().find(template) != -1: return True @@ -112,7 +101,7 @@ def waitformount(template, timeout=50): def waitforunmount(template, timeout=50): - for i in range(timeout): + for _ in range(timeout): if findmnt().find(template) == -1: return True |
