~ [ 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-6.3.13)


  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     56         # Clear KCONFIG_DEFCONFIG_LIST to keep unit tests from being affected
 57         # by the user's environment.               57         # by the user's environment.
 58         extra_env['KCONFIG_DEFCONFIG_LIST'] =      58         extra_env['KCONFIG_DEFCONFIG_LIST'] = ''
 59                                                    59 
 60         # Run Kconfig in a temporary directory     60         # Run Kconfig in a temporary directory.
 61         # This directory is automatically remo     61         # This directory is automatically removed when done.
 62         with tempfile.TemporaryDirectory() as      62         with tempfile.TemporaryDirectory() as temp_dir:
 63                                                    63 
 64             # if .config is given, copy it to      64             # if .config is given, copy it to the working directory
 65             if dot_config:                         65             if dot_config:
 66                 shutil.copyfile(os.path.join(s     66                 shutil.copyfile(os.path.join(self._test_dir, dot_config),
 67                                 os.path.join(t     67                                 os.path.join(temp_dir, '.config'))
 68                                                    68 
 69             ps = subprocess.Popen(command,         69             ps = subprocess.Popen(command,
 70                                   stdin=subpro     70                                   stdin=subprocess.PIPE,
 71                                   stdout=subpr     71                                   stdout=subprocess.PIPE,
 72                                   stderr=subpr     72                                   stderr=subprocess.PIPE,
 73                                   cwd=temp_dir     73                                   cwd=temp_dir,
 74                                   env=dict(os.     74                                   env=dict(os.environ, **extra_env))
 75                                                    75 
 76             # If input key sequence is given,      76             # If input key sequence is given, feed it to stdin.
 77             if in_keys:                            77             if in_keys:
 78                 ps.stdin.write(in_keys.encode(     78                 ps.stdin.write(in_keys.encode('utf-8'))
 79                                                    79 
 80             while ps.poll() is None:               80             while ps.poll() is None:
 81                 # For interactive modes such a     81                 # For interactive modes such as oldaskconfig, oldconfig,
 82                 # send 'Enter' key until the p     82                 # send 'Enter' key until the program finishes.
 83                 if interactive:                    83                 if interactive:
 84                     ps.stdin.write(b'\n')          84                     ps.stdin.write(b'\n')
 85                                                    85 
 86             self.retcode = ps.returncode           86             self.retcode = ps.returncode
 87             self.stdout = ps.stdout.read().dec     87             self.stdout = ps.stdout.read().decode()
 88             self.stderr = ps.stderr.read().dec     88             self.stderr = ps.stderr.read().decode()
 89                                                    89 
 90             # Retrieve the resulted config dat     90             # Retrieve the resulted config data only when .config is supposed
 91             # to exist.  If the command fails,     91             # to exist.  If the command fails, the .config does not exist.
 92             # 'listnewconfig' does not produce     92             # 'listnewconfig' does not produce .config in the first place.
 93             if self.retcode == 0 and out_file:     93             if self.retcode == 0 and out_file:
 94                 with open(os.path.join(temp_di     94                 with open(os.path.join(temp_dir, out_file)) as f:
 95                     self.config = f.read()         95                     self.config = f.read()
 96             else:                                  96             else:
 97                 self.config = None                 97                 self.config = None
 98                                                    98 
 99         # Logging:                                 99         # Logging:
100         # Pytest captures the following inform    100         # Pytest captures the following information by default.  In failure
101         # of tests, the captured log will be d    101         # of tests, the captured log will be displayed.  This will be useful to
102         # figure out what has happened.           102         # figure out what has happened.
103                                                   103 
104         print("[command]\n{}\n".format(' '.joi    104         print("[command]\n{}\n".format(' '.join(command)))
105                                                   105 
106         print("[retcode]\n{}\n".format(self.re    106         print("[retcode]\n{}\n".format(self.retcode))
107                                                   107 
108         print("[stdout]")                         108         print("[stdout]")
109         print(self.stdout)                        109         print(self.stdout)
110                                                   110 
111         print("[stderr]")                         111         print("[stderr]")
112         print(self.stderr)                        112         print(self.stderr)
113                                                   113 
114         if self.config is not None:               114         if self.config is not None:
115             print("[output for '{}']".format(o    115             print("[output for '{}']".format(out_file))
116             print(self.config)                    116             print(self.config)
117                                                   117 
118         return self.retcode                       118         return self.retcode
119                                                   119 
120     def oldaskconfig(self, dot_config=None, in    120     def oldaskconfig(self, dot_config=None, in_keys=None):
121         """Run oldaskconfig.                      121         """Run oldaskconfig.
122                                                   122 
123         dot_config: .config file to use for co    123         dot_config: .config file to use for configuration base (optional)
124         in_key: key inputs (optional)             124         in_key: key inputs (optional)
125         returncode: exit status of the Kconfig    125         returncode: exit status of the Kconfig executable
126         """                                       126         """
127         return self._run_conf('--oldaskconfig'    127         return self._run_conf('--oldaskconfig', dot_config=dot_config,
128                               interactive=True    128                               interactive=True, in_keys=in_keys)
129                                                   129 
130     def oldconfig(self, dot_config=None, in_ke    130     def oldconfig(self, dot_config=None, in_keys=None):
131         """Run oldconfig.                         131         """Run oldconfig.
132                                                   132 
133         dot_config: .config file to use for co    133         dot_config: .config file to use for configuration base (optional)
134         in_key: key inputs (optional)             134         in_key: key inputs (optional)
135         returncode: exit status of the Kconfig    135         returncode: exit status of the Kconfig executable
136         """                                       136         """
137         return self._run_conf('--oldconfig', d    137         return self._run_conf('--oldconfig', dot_config=dot_config,
138                               interactive=True    138                               interactive=True, in_keys=in_keys)
139                                                   139 
140     def olddefconfig(self, dot_config=None):      140     def olddefconfig(self, dot_config=None):
141         """Run olddefconfig.                      141         """Run olddefconfig.
142                                                   142 
143         dot_config: .config file to use for co    143         dot_config: .config file to use for configuration base (optional)
144         returncode: exit status of the Kconfig    144         returncode: exit status of the Kconfig executable
145         """                                       145         """
146         return self._run_conf('--olddefconfig'    146         return self._run_conf('--olddefconfig', dot_config=dot_config)
147                                                   147 
148     def defconfig(self, defconfig):               148     def defconfig(self, defconfig):
149         """Run defconfig.                         149         """Run defconfig.
150                                                   150 
151         defconfig: defconfig file for input       151         defconfig: defconfig file for input
152         returncode: exit status of the Kconfig    152         returncode: exit status of the Kconfig executable
153         """                                       153         """
154         defconfig_path = os.path.join(self._te    154         defconfig_path = os.path.join(self._test_dir, defconfig)
155         return self._run_conf('--defconfig={}'    155         return self._run_conf('--defconfig={}'.format(defconfig_path))
156                                                   156 
157     def _allconfig(self, mode, all_config, ext !! 157     def _allconfig(self, mode, all_config):
158         if all_config:                            158         if all_config:
159             all_config_path = os.path.join(sel    159             all_config_path = os.path.join(self._test_dir, all_config)
160             extra_env['KCONFIG_ALLCONFIG'] = a !! 160             extra_env = {'KCONFIG_ALLCONFIG': all_config_path}
                                                   >> 161         else:
                                                   >> 162             extra_env = {}
161                                                   163 
162         return self._run_conf('--{}config'.for    164         return self._run_conf('--{}config'.format(mode), extra_env=extra_env)
163                                                   165 
164     def allyesconfig(self, all_config=None):      166     def allyesconfig(self, all_config=None):
165         """Run allyesconfig.                      167         """Run allyesconfig.
166                                                   168 
167         all_config: fragment config file for K    169         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
168         returncode: exit status of the Kconfig    170         returncode: exit status of the Kconfig executable
169         """                                       171         """
170         return self._allconfig('allyes', all_c    172         return self._allconfig('allyes', all_config)
171                                                   173 
172     def allmodconfig(self, all_config=None):      174     def allmodconfig(self, all_config=None):
173         """Run allmodconfig.                      175         """Run allmodconfig.
174                                                   176 
175         all_config: fragment config file for K    177         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
176         returncode: exit status of the Kconfig    178         returncode: exit status of the Kconfig executable
177         """                                       179         """
178         return self._allconfig('allmod', all_c    180         return self._allconfig('allmod', all_config)
179                                                   181 
180     def allnoconfig(self, all_config=None):       182     def allnoconfig(self, all_config=None):
181         """Run allnoconfig.                       183         """Run allnoconfig.
182                                                   184 
183         all_config: fragment config file for K    185         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
184         returncode: exit status of the Kconfig    186         returncode: exit status of the Kconfig executable
185         """                                       187         """
186         return self._allconfig('allno', all_co    188         return self._allconfig('allno', all_config)
187                                                   189 
188     def alldefconfig(self, all_config=None):      190     def alldefconfig(self, all_config=None):
189         """Run alldefconfig.                      191         """Run alldefconfig.
190                                                   192 
191         all_config: fragment config file for K    193         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
192         returncode: exit status of the Kconfig    194         returncode: exit status of the Kconfig executable
193         """                                       195         """
194         return self._allconfig('alldef', all_c    196         return self._allconfig('alldef', all_config)
195                                                   197 
196     def randconfig(self, all_config=None, seed !! 198     def randconfig(self, all_config=None):
197         """Run randconfig.                        199         """Run randconfig.
198                                                   200 
199         all_config: fragment config file for K    201         all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
200         seed: the seed for randconfig (optiona << 
201         returncode: exit status of the Kconfig    202         returncode: exit status of the Kconfig executable
202         """                                       203         """
203         if seed is not None:                   !! 204         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                                                   205 
210     def savedefconfig(self, dot_config):          206     def savedefconfig(self, dot_config):
211         """Run savedefconfig.                     207         """Run savedefconfig.
212                                                   208 
213         dot_config: .config file for input        209         dot_config: .config file for input
214         returncode: exit status of the Kconfig    210         returncode: exit status of the Kconfig executable
215         """                                       211         """
216         return self._run_conf('--savedefconfig    212         return self._run_conf('--savedefconfig', out_file='defconfig')
217                                                   213 
218     def listnewconfig(self, dot_config=None):     214     def listnewconfig(self, dot_config=None):
219         """Run listnewconfig.                     215         """Run listnewconfig.
220                                                   216 
221         dot_config: .config file to use for co    217         dot_config: .config file to use for configuration base (optional)
222         returncode: exit status of the Kconfig    218         returncode: exit status of the Kconfig executable
223         """                                       219         """
224         return self._run_conf('--listnewconfig    220         return self._run_conf('--listnewconfig', dot_config=dot_config,
225                               out_file=None)      221                               out_file=None)
226                                                   222 
227     # checkers                                    223     # checkers
228     def _read_and_compare(self, compare, expec    224     def _read_and_compare(self, compare, expected):
229         """Compare the result with expectation    225         """Compare the result with expectation.
230                                                   226 
231         compare: function to compare the resul    227         compare: function to compare the result with expectation
232         expected: file that contains the expec    228         expected: file that contains the expected data
233         """                                       229         """
234         with open(os.path.join(self._test_dir,    230         with open(os.path.join(self._test_dir, expected)) as f:
235             expected_data = f.read()              231             expected_data = f.read()
236         return compare(self, expected_data)       232         return compare(self, expected_data)
237                                                   233 
238     def _contains(self, attr, expected):          234     def _contains(self, attr, expected):
239         return self._read_and_compare(            235         return self._read_and_compare(
240                                     lambda s,     236                                     lambda s, e: getattr(s, attr).find(e) >= 0,
241                                     expected)     237                                     expected)
242                                                   238 
243     def _matches(self, attr, expected):           239     def _matches(self, attr, expected):
244         return self._read_and_compare(lambda s    240         return self._read_and_compare(lambda s, e: getattr(s, attr) == e,
245                                       expected    241                                       expected)
246                                                   242 
247     def config_contains(self, expected):          243     def config_contains(self, expected):
248         """Check if resulted configuration con    244         """Check if resulted configuration contains expected data.
249                                                   245 
250         expected: file that contains the expec    246         expected: file that contains the expected data
251         returncode: True if result contains th    247         returncode: True if result contains the expected data, False otherwise
252         """                                       248         """
253         return self._contains('config', expect    249         return self._contains('config', expected)
254                                                   250 
255     def config_matches(self, expected):           251     def config_matches(self, expected):
256         """Check if resulted configuration exa    252         """Check if resulted configuration exactly matches expected data.
257                                                   253 
258         expected: file that contains the expec    254         expected: file that contains the expected data
259         returncode: True if result matches the    255         returncode: True if result matches the expected data, False otherwise
260         """                                       256         """
261         return self._matches('config', expecte    257         return self._matches('config', expected)
262                                                   258 
263     def stdout_contains(self, expected):          259     def stdout_contains(self, expected):
264         """Check if resulted stdout contains e    260         """Check if resulted stdout contains expected data.
265                                                   261 
266         expected: file that contains the expec    262         expected: file that contains the expected data
267         returncode: True if result contains th    263         returncode: True if result contains the expected data, False otherwise
268         """                                       264         """
269         return self._contains('stdout', expect    265         return self._contains('stdout', expected)
270                                                   266 
271     def stdout_matches(self, expected):           267     def stdout_matches(self, expected):
272         """Check if resulted stdout exactly ma    268         """Check if resulted stdout exactly matches expected data.
273                                                   269 
274         expected: file that contains the expec    270         expected: file that contains the expected data
275         returncode: True if result matches the    271         returncode: True if result matches the expected data, False otherwise
276         """                                       272         """
277         return self._matches('stdout', expecte    273         return self._matches('stdout', expected)
278                                                   274 
279     def stderr_contains(self, expected):          275     def stderr_contains(self, expected):
280         """Check if resulted stderr contains e    276         """Check if resulted stderr contains expected data.
281                                                   277 
282         expected: file that contains the expec    278         expected: file that contains the expected data
283         returncode: True if result contains th    279         returncode: True if result contains the expected data, False otherwise
284         """                                       280         """
285         return self._contains('stderr', expect    281         return self._contains('stderr', expected)
286                                                   282 
287     def stderr_matches(self, expected):           283     def stderr_matches(self, expected):
288         """Check if resulted stderr exactly ma    284         """Check if resulted stderr exactly matches expected data.
289                                                   285 
290         expected: file that contains the expec    286         expected: file that contains the expected data
291         returncode: True if result matches the    287         returncode: True if result matches the expected data, False otherwise
292         """                                       288         """
293         return self._matches('stderr', expecte    289         return self._matches('stderr', expected)
294                                                   290 
295                                                   291 
296 @pytest.fixture(scope="module")                   292 @pytest.fixture(scope="module")
297 def conf(request):                                293 def conf(request):
298     """Create a Conf instance and provide it t    294     """Create a Conf instance and provide it to test functions."""
299     return Conf(request)                          295     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