Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) # Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) Kconfig unit testing framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) This provides fixture functions commonly used from test files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) import pytest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) import shutil
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) import subprocess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) import tempfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) CONF_PATH = os.path.abspath(os.path.join('scripts', 'kconfig', 'conf'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) class Conf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)     """Kconfig runner and result checker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)     This class provides methods to run text-based interface of Kconfig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)     (scripts/kconfig/conf) and retrieve the resulted configuration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)     stdout, and stderr.  It also provides methods to compare those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)     results with expectations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)     def __init__(self, request):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)         """Create a new Conf instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)         request: object to introspect the requesting test module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)         # the directory of the test being run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)         self._test_dir = os.path.dirname(str(request.fspath))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)     # runners
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)     def _run_conf(self, mode, dot_config=None, out_file='.config',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)                   interactive=False, in_keys=None, extra_env={}):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)         """Run text-based Kconfig executable and save the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)         mode: input mode option (--oldaskconfig, --defconfig=<file> etc.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)         dot_config: .config file to use for configuration base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)         out_file: file name to contain the output config data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)         interactive: flag to specify the interactive mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)         in_keys: key inputs for interactive modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)         extra_env: additional environments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)         command = [CONF_PATH, mode, 'Kconfig']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)         # Override 'srctree' environment to make the test as the top directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)         extra_env['srctree'] = self._test_dir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)         # Run Kconfig in a temporary directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)         # This directory is automatically removed when done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)         with tempfile.TemporaryDirectory() as temp_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)             # if .config is given, copy it to the working directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)             if dot_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)                 shutil.copyfile(os.path.join(self._test_dir, dot_config),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)                                 os.path.join(temp_dir, '.config'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)             ps = subprocess.Popen(command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)                                   stdin=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)                                   stdout=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)                                   stderr=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)                                   cwd=temp_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)                                   env=dict(os.environ, **extra_env))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)             # If input key sequence is given, feed it to stdin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)             if in_keys:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)                 ps.stdin.write(in_keys.encode('utf-8'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)             while ps.poll() is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)                 # For interactive modes such as oldaskconfig, oldconfig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)                 # send 'Enter' key until the program finishes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)                 if interactive:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)                     ps.stdin.write(b'\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)             self.retcode = ps.returncode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)             self.stdout = ps.stdout.read().decode()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)             self.stderr = ps.stderr.read().decode()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)             # Retrieve the resulted config data only when .config is supposed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)             # to exist.  If the command fails, the .config does not exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)             # 'listnewconfig' does not produce .config in the first place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)             if self.retcode == 0 and out_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)                 with open(os.path.join(temp_dir, out_file)) as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)                     self.config = f.read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)             else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)                 self.config = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)         # Logging:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)         # Pytest captures the following information by default.  In failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)         # of tests, the captured log will be displayed.  This will be useful to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)         # figure out what has happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)         print("[command]\n{}\n".format(' '.join(command)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)         print("[retcode]\n{}\n".format(self.retcode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)         print("[stdout]")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)         print(self.stdout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)         print("[stderr]")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)         print(self.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)         if self.config is not None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)             print("[output for '{}']".format(out_file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)             print(self.config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)         return self.retcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)     def oldaskconfig(self, dot_config=None, in_keys=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)         """Run oldaskconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)         dot_config: .config file to use for configuration base (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)         in_key: key inputs (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)         return self._run_conf('--oldaskconfig', dot_config=dot_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)                               interactive=True, in_keys=in_keys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)     def oldconfig(self, dot_config=None, in_keys=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)         """Run oldconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)         dot_config: .config file to use for configuration base (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)         in_key: key inputs (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)         return self._run_conf('--oldconfig', dot_config=dot_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)                               interactive=True, in_keys=in_keys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     def olddefconfig(self, dot_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)         """Run olddefconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)         dot_config: .config file to use for configuration base (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)         return self._run_conf('--olddefconfig', dot_config=dot_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)     def defconfig(self, defconfig):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)         """Run defconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)         defconfig: defconfig file for input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)         defconfig_path = os.path.join(self._test_dir, defconfig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)         return self._run_conf('--defconfig={}'.format(defconfig_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)     def _allconfig(self, mode, all_config):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)         if all_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)             all_config_path = os.path.join(self._test_dir, all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)             extra_env = {'KCONFIG_ALLCONFIG': all_config_path}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)             extra_env = {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)         return self._run_conf('--{}config'.format(mode), extra_env=extra_env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)     def allyesconfig(self, all_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)         """Run allyesconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)         return self._allconfig('allyes', all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)     def allmodconfig(self, all_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)         """Run allmodconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)         return self._allconfig('allmod', all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)     def allnoconfig(self, all_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)         """Run allnoconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)         return self._allconfig('allno', all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)     def alldefconfig(self, all_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)         """Run alldefconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)         return self._allconfig('alldef', all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)     def randconfig(self, all_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)         """Run randconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)         return self._allconfig('rand', all_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)     def savedefconfig(self, dot_config):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)         """Run savedefconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)         dot_config: .config file for input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)         return self._run_conf('--savedefconfig', out_file='defconfig')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)     def listnewconfig(self, dot_config=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)         """Run listnewconfig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)         dot_config: .config file to use for configuration base (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)         returncode: exit status of the Kconfig executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)         return self._run_conf('--listnewconfig', dot_config=dot_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)                               out_file=None)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)     # checkers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)     def _read_and_compare(self, compare, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)         """Compare the result with expectation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)         compare: function to compare the result with expectation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)         with open(os.path.join(self._test_dir, expected)) as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)             expected_data = f.read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)         return compare(self, expected_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)     def _contains(self, attr, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)         return self._read_and_compare(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)                                     lambda s, e: getattr(s, attr).find(e) >= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)                                     expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)     def _matches(self, attr, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)         return self._read_and_compare(lambda s, e: getattr(s, attr) == e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)                                       expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)     def config_contains(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)         """Check if resulted configuration contains expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)         returncode: True if result contains the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)         return self._contains('config', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)     def config_matches(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)         """Check if resulted configuration exactly matches expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)         returncode: True if result matches the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)         return self._matches('config', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)     def stdout_contains(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)         """Check if resulted stdout contains expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)         returncode: True if result contains the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)         return self._contains('stdout', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)     def stdout_matches(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)         """Check if resulted stdout exactly matches expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)         returncode: True if result matches the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)         return self._matches('stdout', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)     def stderr_contains(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)         """Check if resulted stderr contains expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)         returncode: True if result contains the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)         return self._contains('stderr', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)     def stderr_matches(self, expected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)         """Check if resulted stderr exactly matches expected data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)         expected: file that contains the expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)         returncode: True if result matches the expected data, False otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)         """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)         return self._matches('stderr', expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) @pytest.fixture(scope="module")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) def conf(request):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)     """Create a Conf instance and provide it to test functions."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)     return Conf(request)