~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kconfig/tests/conftest.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/kconfig/tests/conftest.py (Version linux-6.12-rc7) and /scripts/kconfig/tests/conftest.py (Version linux-5.4.285)


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php