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

TOMOYO Linux Cross Reference
Linux/tools/testing/kunit/kunit_kernel.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 /tools/testing/kunit/kunit_kernel.py (Architecture ppc) and /tools/testing/kunit/kunit_kernel.py (Architecture mips)


  1 # SPDX-License-Identifier: GPL-2.0                  1 # SPDX-License-Identifier: GPL-2.0
  2 #                                                   2 #
  3 # Runs UML kernel, collects output, and handle      3 # Runs UML kernel, collects output, and handles errors.
  4 #                                                   4 #
  5 # Copyright (C) 2019, Google LLC.                   5 # Copyright (C) 2019, Google LLC.
  6 # Author: Felix Guo <felixguoxiuping@gmail.com>      6 # Author: Felix Guo <felixguoxiuping@gmail.com>
  7 # Author: Brendan Higgins <brendanhiggins@googl      7 # Author: Brendan Higgins <brendanhiggins@google.com>
  8                                                     8 
  9 import importlib.abc                                9 import importlib.abc
 10 import importlib.util                              10 import importlib.util
 11 import logging                                     11 import logging
 12 import subprocess                                  12 import subprocess
 13 import os                                          13 import os
 14 import shlex                                       14 import shlex
 15 import shutil                                      15 import shutil
 16 import signal                                      16 import signal
 17 import threading                                   17 import threading
 18 from typing import Iterator, List, Optional, T     18 from typing import Iterator, List, Optional, Tuple
 19 from types import FrameType                        19 from types import FrameType
 20                                                    20 
 21 import kunit_config                                21 import kunit_config
 22 import qemu_config                                 22 import qemu_config
 23                                                    23 
 24 KCONFIG_PATH = '.config'                           24 KCONFIG_PATH = '.config'
 25 KUNITCONFIG_PATH = '.kunitconfig'                  25 KUNITCONFIG_PATH = '.kunitconfig'
 26 OLD_KUNITCONFIG_PATH = 'last_used_kunitconfig'     26 OLD_KUNITCONFIG_PATH = 'last_used_kunitconfig'
 27 DEFAULT_KUNITCONFIG_PATH = 'tools/testing/kuni     27 DEFAULT_KUNITCONFIG_PATH = 'tools/testing/kunit/configs/default.config'
 28 ALL_TESTS_CONFIG_PATH = 'tools/testing/kunit/c     28 ALL_TESTS_CONFIG_PATH = 'tools/testing/kunit/configs/all_tests.config'
 29 UML_KCONFIG_PATH = 'tools/testing/kunit/config     29 UML_KCONFIG_PATH = 'tools/testing/kunit/configs/arch_uml.config'
 30 OUTFILE_PATH = 'test.log'                          30 OUTFILE_PATH = 'test.log'
 31 ABS_TOOL_PATH = os.path.abspath(os.path.dirnam     31 ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__))
 32 QEMU_CONFIGS_DIR = os.path.join(ABS_TOOL_PATH,     32 QEMU_CONFIGS_DIR = os.path.join(ABS_TOOL_PATH, 'qemu_configs')
 33                                                    33 
 34 class ConfigError(Exception):                      34 class ConfigError(Exception):
 35         """Represents an error trying to confi     35         """Represents an error trying to configure the Linux kernel."""
 36                                                    36 
 37                                                    37 
 38 class BuildError(Exception):                       38 class BuildError(Exception):
 39         """Represents an error trying to build     39         """Represents an error trying to build the Linux kernel."""
 40                                                    40 
 41                                                    41 
 42 class LinuxSourceTreeOperations:                   42 class LinuxSourceTreeOperations:
 43         """An abstraction over command line op     43         """An abstraction over command line operations performed on a source tree."""
 44                                                    44 
 45         def __init__(self, linux_arch: str, cr     45         def __init__(self, linux_arch: str, cross_compile: Optional[str]):
 46                 self._linux_arch = linux_arch      46                 self._linux_arch = linux_arch
 47                 self._cross_compile = cross_co     47                 self._cross_compile = cross_compile
 48                                                    48 
 49         def make_mrproper(self) -> None:           49         def make_mrproper(self) -> None:
 50                 try:                               50                 try:
 51                         subprocess.check_outpu     51                         subprocess.check_output(['make', 'mrproper'], stderr=subprocess.STDOUT)
 52                 except OSError as e:               52                 except OSError as e:
 53                         raise ConfigError('Cou     53                         raise ConfigError('Could not call make command: ' + str(e))
 54                 except subprocess.CalledProces     54                 except subprocess.CalledProcessError as e:
 55                         raise ConfigError(e.ou     55                         raise ConfigError(e.output.decode())
 56                                                    56 
 57         def make_arch_config(self, base_kunitc     57         def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
 58                 return base_kunitconfig            58                 return base_kunitconfig
 59                                                    59 
 60         def make_olddefconfig(self, build_dir:     60         def make_olddefconfig(self, build_dir: str, make_options: Optional[List[str]]) -> None:
 61                 command = ['make', 'ARCH=' + s     61                 command = ['make', 'ARCH=' + self._linux_arch, 'O=' + build_dir, 'olddefconfig']
 62                 if self._cross_compile:            62                 if self._cross_compile:
 63                         command += ['CROSS_COM     63                         command += ['CROSS_COMPILE=' + self._cross_compile]
 64                 if make_options:                   64                 if make_options:
 65                         command.extend(make_op     65                         command.extend(make_options)
 66                 print('Populating config with:     66                 print('Populating config with:\n$', ' '.join(command))
 67                 try:                               67                 try:
 68                         subprocess.check_outpu     68                         subprocess.check_output(command, stderr=subprocess.STDOUT)
 69                 except OSError as e:               69                 except OSError as e:
 70                         raise ConfigError('Cou     70                         raise ConfigError('Could not call make command: ' + str(e))
 71                 except subprocess.CalledProces     71                 except subprocess.CalledProcessError as e:
 72                         raise ConfigError(e.ou     72                         raise ConfigError(e.output.decode())
 73                                                    73 
 74         def make(self, jobs: int, build_dir: s     74         def make(self, jobs: int, build_dir: str, make_options: Optional[List[str]]) -> None:
 75                 command = ['make', 'all', 'com     75                 command = ['make', 'all', 'compile_commands.json', 'ARCH=' + self._linux_arch,
 76                            'O=' + build_dir, '     76                            'O=' + build_dir, '--jobs=' + str(jobs)]
 77                 if make_options:                   77                 if make_options:
 78                         command.extend(make_op     78                         command.extend(make_options)
 79                 if self._cross_compile:            79                 if self._cross_compile:
 80                         command += ['CROSS_COM     80                         command += ['CROSS_COMPILE=' + self._cross_compile]
 81                 print('Building with:\n$', ' '     81                 print('Building with:\n$', ' '.join(command))
 82                 try:                               82                 try:
 83                         proc = subprocess.Pope     83                         proc = subprocess.Popen(command,
 84                                                    84                                                 stderr=subprocess.PIPE,
 85                                                    85                                                 stdout=subprocess.DEVNULL)
 86                 except OSError as e:               86                 except OSError as e:
 87                         raise BuildError('Coul     87                         raise BuildError('Could not call execute make: ' + str(e))
 88                 except subprocess.CalledProces     88                 except subprocess.CalledProcessError as e:
 89                         raise BuildError(e.out     89                         raise BuildError(e.output)
 90                 _, stderr = proc.communicate()     90                 _, stderr = proc.communicate()
 91                 if proc.returncode != 0:           91                 if proc.returncode != 0:
 92                         raise BuildError(stder     92                         raise BuildError(stderr.decode())
 93                 if stderr:  # likely only due      93                 if stderr:  # likely only due to build warnings
 94                         print(stderr.decode())     94                         print(stderr.decode())
 95                                                    95 
 96         def start(self, params: List[str], bui     96         def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
 97                 raise RuntimeError('not implem     97                 raise RuntimeError('not implemented!')
 98                                                    98 
 99                                                    99 
100 class LinuxSourceTreeOperationsQemu(LinuxSourc    100 class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
101                                                   101 
102         def __init__(self, qemu_arch_params: q    102         def __init__(self, qemu_arch_params: qemu_config.QemuArchParams, cross_compile: Optional[str]):
103                 super().__init__(linux_arch=qe    103                 super().__init__(linux_arch=qemu_arch_params.linux_arch,
104                                  cross_compile    104                                  cross_compile=cross_compile)
105                 self._kconfig = qemu_arch_para    105                 self._kconfig = qemu_arch_params.kconfig
106                 self._qemu_arch = qemu_arch_pa    106                 self._qemu_arch = qemu_arch_params.qemu_arch
107                 self._kernel_path = qemu_arch_    107                 self._kernel_path = qemu_arch_params.kernel_path
108                 self._kernel_command_line = qe    108                 self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot'
109                 self._extra_qemu_params = qemu    109                 self._extra_qemu_params = qemu_arch_params.extra_qemu_params
110                 self._serial = qemu_arch_param    110                 self._serial = qemu_arch_params.serial
111                                                   111 
112         def make_arch_config(self, base_kunitc    112         def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
113                 kconfig = kunit_config.parse_f    113                 kconfig = kunit_config.parse_from_string(self._kconfig)
114                 kconfig.merge_in_entries(base_    114                 kconfig.merge_in_entries(base_kunitconfig)
115                 return kconfig                    115                 return kconfig
116                                                   116 
117         def start(self, params: List[str], bui    117         def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
118                 kernel_path = os.path.join(bui    118                 kernel_path = os.path.join(build_dir, self._kernel_path)
119                 qemu_command = ['qemu-system-'    119                 qemu_command = ['qemu-system-' + self._qemu_arch,
120                                 '-nodefaults',    120                                 '-nodefaults',
121                                 '-m', '1024',     121                                 '-m', '1024',
122                                 '-kernel', ker    122                                 '-kernel', kernel_path,
123                                 '-append', ' '    123                                 '-append', ' '.join(params + [self._kernel_command_line]),
124                                 '-no-reboot',     124                                 '-no-reboot',
125                                 '-nographic',     125                                 '-nographic',
126                                 '-serial', sel    126                                 '-serial', self._serial] + self._extra_qemu_params
127                 # Note: shlex.join() does what    127                 # Note: shlex.join() does what we want, but requires python 3.8+.
128                 print('Running tests with:\n$'    128                 print('Running tests with:\n$', ' '.join(shlex.quote(arg) for arg in qemu_command))
129                 return subprocess.Popen(qemu_c    129                 return subprocess.Popen(qemu_command,
130                                         stdin=    130                                         stdin=subprocess.PIPE,
131                                         stdout    131                                         stdout=subprocess.PIPE,
132                                         stderr    132                                         stderr=subprocess.STDOUT,
133                                         text=T    133                                         text=True, errors='backslashreplace')
134                                                   134 
135 class LinuxSourceTreeOperationsUml(LinuxSource    135 class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations):
136         """An abstraction over command line op    136         """An abstraction over command line operations performed on a source tree."""
137                                                   137 
138         def __init__(self, cross_compile: Opti    138         def __init__(self, cross_compile: Optional[str]=None):
139                 super().__init__(linux_arch='u    139                 super().__init__(linux_arch='um', cross_compile=cross_compile)
140                                                   140 
141         def make_arch_config(self, base_kunitc    141         def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
142                 kconfig = kunit_config.parse_f    142                 kconfig = kunit_config.parse_file(UML_KCONFIG_PATH)
143                 kconfig.merge_in_entries(base_    143                 kconfig.merge_in_entries(base_kunitconfig)
144                 return kconfig                    144                 return kconfig
145                                                   145 
146         def start(self, params: List[str], bui    146         def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
147                 """Runs the Linux UML binary.     147                 """Runs the Linux UML binary. Must be named 'linux'."""
148                 linux_bin = os.path.join(build    148                 linux_bin = os.path.join(build_dir, 'linux')
149                 params.extend(['mem=1G', 'cons    149                 params.extend(['mem=1G', 'console=tty', 'kunit_shutdown=halt'])
150                 print('Running tests with:\n$'    150                 print('Running tests with:\n$', linux_bin, ' '.join(shlex.quote(arg) for arg in params))
151                 return subprocess.Popen([linux    151                 return subprocess.Popen([linux_bin] + params,
152                                            std    152                                            stdin=subprocess.PIPE,
153                                            std    153                                            stdout=subprocess.PIPE,
154                                            std    154                                            stderr=subprocess.STDOUT,
155                                            tex    155                                            text=True, errors='backslashreplace')
156                                                   156 
157 def get_kconfig_path(build_dir: str) -> str:      157 def get_kconfig_path(build_dir: str) -> str:
158         return os.path.join(build_dir, KCONFIG    158         return os.path.join(build_dir, KCONFIG_PATH)
159                                                   159 
160 def get_kunitconfig_path(build_dir: str) -> st    160 def get_kunitconfig_path(build_dir: str) -> str:
161         return os.path.join(build_dir, KUNITCO    161         return os.path.join(build_dir, KUNITCONFIG_PATH)
162                                                   162 
163 def get_old_kunitconfig_path(build_dir: str) -    163 def get_old_kunitconfig_path(build_dir: str) -> str:
164         return os.path.join(build_dir, OLD_KUN    164         return os.path.join(build_dir, OLD_KUNITCONFIG_PATH)
165                                                   165 
166 def get_parsed_kunitconfig(build_dir: str,        166 def get_parsed_kunitconfig(build_dir: str,
167                            kunitconfig_paths:     167                            kunitconfig_paths: Optional[List[str]]=None) -> kunit_config.Kconfig:
168         if not kunitconfig_paths:                 168         if not kunitconfig_paths:
169                 path = get_kunitconfig_path(bu    169                 path = get_kunitconfig_path(build_dir)
170                 if not os.path.exists(path):      170                 if not os.path.exists(path):
171                         shutil.copyfile(DEFAUL    171                         shutil.copyfile(DEFAULT_KUNITCONFIG_PATH, path)
172                 return kunit_config.parse_file    172                 return kunit_config.parse_file(path)
173                                                   173 
174         merged = kunit_config.Kconfig()           174         merged = kunit_config.Kconfig()
175                                                   175 
176         for path in kunitconfig_paths:            176         for path in kunitconfig_paths:
177                 if os.path.isdir(path):           177                 if os.path.isdir(path):
178                         path = os.path.join(pa    178                         path = os.path.join(path, KUNITCONFIG_PATH)
179                 if not os.path.exists(path):      179                 if not os.path.exists(path):
180                         raise ConfigError(f'Sp    180                         raise ConfigError(f'Specified kunitconfig ({path}) does not exist')
181                                                   181 
182                 partial = kunit_config.parse_f    182                 partial = kunit_config.parse_file(path)
183                 diff = merged.conflicting_opti    183                 diff = merged.conflicting_options(partial)
184                 if diff:                          184                 if diff:
185                         diff_str = '\n\n'.join    185                         diff_str = '\n\n'.join(f'{a}\n  vs from {path}\n{b}' for a, b in diff)
186                         raise ConfigError(f'Mu    186                         raise ConfigError(f'Multiple values specified for {len(diff)} options in kunitconfig:\n{diff_str}')
187                 merged.merge_in_entries(partia    187                 merged.merge_in_entries(partial)
188         return merged                             188         return merged
189                                                   189 
190 def get_outfile_path(build_dir: str) -> str:      190 def get_outfile_path(build_dir: str) -> str:
191         return os.path.join(build_dir, OUTFILE    191         return os.path.join(build_dir, OUTFILE_PATH)
192                                                   192 
193 def _default_qemu_config_path(arch: str) -> st    193 def _default_qemu_config_path(arch: str) -> str:
194         config_path = os.path.join(QEMU_CONFIG    194         config_path = os.path.join(QEMU_CONFIGS_DIR, arch + '.py')
195         if os.path.isfile(config_path):           195         if os.path.isfile(config_path):
196                 return config_path                196                 return config_path
197                                                   197 
198         options = [f[:-3] for f in os.listdir(    198         options = [f[:-3] for f in os.listdir(QEMU_CONFIGS_DIR) if f.endswith('.py')]
199         raise ConfigError(arch + ' is not a va    199         raise ConfigError(arch + ' is not a valid arch, options are ' + str(sorted(options)))
200                                                   200 
201 def _get_qemu_ops(config_path: str,               201 def _get_qemu_ops(config_path: str,
202                   extra_qemu_args: Optional[Li    202                   extra_qemu_args: Optional[List[str]],
203                   cross_compile: Optional[str]    203                   cross_compile: Optional[str]) -> Tuple[str, LinuxSourceTreeOperations]:
204         # The module name/path has very little    204         # The module name/path has very little to do with where the actual file
205         # exists (I learned this through exper    205         # exists (I learned this through experimentation and could not find it
206         # anywhere in the Python documentation    206         # anywhere in the Python documentation).
207         #                                         207         #
208         # Bascially, we completely ignore the     208         # Bascially, we completely ignore the actual file location of the config
209         # we are loading and just tell Python     209         # we are loading and just tell Python that the module lives in the
210         # QEMU_CONFIGS_DIR for import purposes    210         # QEMU_CONFIGS_DIR for import purposes regardless of where it actually
211         # exists as a file.                       211         # exists as a file.
212         module_path = '.' + os.path.join(os.pa    212         module_path = '.' + os.path.join(os.path.basename(QEMU_CONFIGS_DIR), os.path.basename(config_path))
213         spec = importlib.util.spec_from_file_l    213         spec = importlib.util.spec_from_file_location(module_path, config_path)
214         assert spec is not None                   214         assert spec is not None
215         config = importlib.util.module_from_sp    215         config = importlib.util.module_from_spec(spec)
216         # See https://github.com/python/typesh    216         # See https://github.com/python/typeshed/pull/2626 for context.
217         assert isinstance(spec.loader, importl    217         assert isinstance(spec.loader, importlib.abc.Loader)
218         spec.loader.exec_module(config)           218         spec.loader.exec_module(config)
219                                                   219 
220         if not hasattr(config, 'QEMU_ARCH'):      220         if not hasattr(config, 'QEMU_ARCH'):
221                 raise ValueError('qemu_config     221                 raise ValueError('qemu_config module missing "QEMU_ARCH": ' + config_path)
222         params: qemu_config.QemuArchParams = c    222         params: qemu_config.QemuArchParams = config.QEMU_ARCH
223         if extra_qemu_args:                       223         if extra_qemu_args:
224                 params.extra_qemu_params.exten    224                 params.extra_qemu_params.extend(extra_qemu_args)
225         return params.linux_arch, LinuxSourceT    225         return params.linux_arch, LinuxSourceTreeOperationsQemu(
226                         params, cross_compile=    226                         params, cross_compile=cross_compile)
227                                                   227 
228 class LinuxSourceTree:                            228 class LinuxSourceTree:
229         """Represents a Linux kernel source tr    229         """Represents a Linux kernel source tree with KUnit tests."""
230                                                   230 
231         def __init__(                             231         def __init__(
232               self,                               232               self,
233               build_dir: str,                     233               build_dir: str,
234               kunitconfig_paths: Optional[List    234               kunitconfig_paths: Optional[List[str]]=None,
235               kconfig_add: Optional[List[str]]    235               kconfig_add: Optional[List[str]]=None,
236               arch: Optional[str]=None,           236               arch: Optional[str]=None,
237               cross_compile: Optional[str]=Non    237               cross_compile: Optional[str]=None,
238               qemu_config_path: Optional[str]=    238               qemu_config_path: Optional[str]=None,
239               extra_qemu_args: Optional[List[s    239               extra_qemu_args: Optional[List[str]]=None) -> None:
240                 signal.signal(signal.SIGINT, s    240                 signal.signal(signal.SIGINT, self.signal_handler)
241                 if qemu_config_path:              241                 if qemu_config_path:
242                         self._arch, self._ops     242                         self._arch, self._ops = _get_qemu_ops(qemu_config_path, extra_qemu_args, cross_compile)
243                 else:                             243                 else:
244                         self._arch = 'um' if a    244                         self._arch = 'um' if arch is None else arch
245                         if self._arch == 'um':    245                         if self._arch == 'um':
246                                 self._ops = Li    246                                 self._ops = LinuxSourceTreeOperationsUml(cross_compile=cross_compile)
247                         else:                     247                         else:
248                                 qemu_config_pa    248                                 qemu_config_path = _default_qemu_config_path(self._arch)
249                                 _, self._ops =    249                                 _, self._ops = _get_qemu_ops(qemu_config_path, extra_qemu_args, cross_compile)
250                                                   250 
251                 self._kconfig = get_parsed_kun    251                 self._kconfig = get_parsed_kunitconfig(build_dir, kunitconfig_paths)
252                 if kconfig_add:                   252                 if kconfig_add:
253                         kconfig = kunit_config    253                         kconfig = kunit_config.parse_from_string('\n'.join(kconfig_add))
254                         self._kconfig.merge_in    254                         self._kconfig.merge_in_entries(kconfig)
255                                                   255 
256         def arch(self) -> str:                    256         def arch(self) -> str:
257                 return self._arch                 257                 return self._arch
258                                                   258 
259         def clean(self) -> bool:                  259         def clean(self) -> bool:
260                 try:                              260                 try:
261                         self._ops.make_mrprope    261                         self._ops.make_mrproper()
262                 except ConfigError as e:          262                 except ConfigError as e:
263                         logging.error(e)          263                         logging.error(e)
264                         return False              264                         return False
265                 return True                       265                 return True
266                                                   266 
267         def validate_config(self, build_dir: s    267         def validate_config(self, build_dir: str) -> bool:
268                 kconfig_path = get_kconfig_pat    268                 kconfig_path = get_kconfig_path(build_dir)
269                 validated_kconfig = kunit_conf    269                 validated_kconfig = kunit_config.parse_file(kconfig_path)
270                 if self._kconfig.is_subset_of(    270                 if self._kconfig.is_subset_of(validated_kconfig):
271                         return True               271                         return True
272                 missing = set(self._kconfig.as    272                 missing = set(self._kconfig.as_entries()) - set(validated_kconfig.as_entries())
273                 message = 'Not all Kconfig opt    273                 message = 'Not all Kconfig options selected in kunitconfig were in the generated .config.\n' \
274                           'This is probably du    274                           'This is probably due to unsatisfied dependencies.\n' \
275                           'Missing: ' + ', '.j    275                           'Missing: ' + ', '.join(str(e) for e in missing)
276                 if self._arch == 'um':            276                 if self._arch == 'um':
277                         message += '\nNote: ma    277                         message += '\nNote: many Kconfig options aren\'t available on UML. You can try running ' \
278                                    'on a diffe    278                                    'on a different architecture with something like "--arch=x86_64".'
279                 logging.error(message)            279                 logging.error(message)
280                 return False                      280                 return False
281                                                   281 
282         def build_config(self, build_dir: str,    282         def build_config(self, build_dir: str, make_options: Optional[List[str]]) -> bool:
283                 kconfig_path = get_kconfig_pat    283                 kconfig_path = get_kconfig_path(build_dir)
284                 if build_dir and not os.path.e    284                 if build_dir and not os.path.exists(build_dir):
285                         os.mkdir(build_dir)       285                         os.mkdir(build_dir)
286                 try:                              286                 try:
287                         self._kconfig = self._    287                         self._kconfig = self._ops.make_arch_config(self._kconfig)
288                         self._kconfig.write_to    288                         self._kconfig.write_to_file(kconfig_path)
289                         self._ops.make_olddefc    289                         self._ops.make_olddefconfig(build_dir, make_options)
290                 except ConfigError as e:          290                 except ConfigError as e:
291                         logging.error(e)          291                         logging.error(e)
292                         return False              292                         return False
293                 if not self.validate_config(bu    293                 if not self.validate_config(build_dir):
294                         return False              294                         return False
295                                                   295 
296                 old_path = get_old_kunitconfig    296                 old_path = get_old_kunitconfig_path(build_dir)
297                 if os.path.exists(old_path):      297                 if os.path.exists(old_path):
298                         os.remove(old_path)  #    298                         os.remove(old_path)  # write_to_file appends to the file
299                 self._kconfig.write_to_file(ol    299                 self._kconfig.write_to_file(old_path)
300                 return True                       300                 return True
301                                                   301 
302         def _kunitconfig_changed(self, build_d    302         def _kunitconfig_changed(self, build_dir: str) -> bool:
303                 old_path = get_old_kunitconfig    303                 old_path = get_old_kunitconfig_path(build_dir)
304                 if not os.path.exists(old_path    304                 if not os.path.exists(old_path):
305                         return True               305                         return True
306                                                   306 
307                 old_kconfig = kunit_config.par    307                 old_kconfig = kunit_config.parse_file(old_path)
308                 return old_kconfig != self._kc    308                 return old_kconfig != self._kconfig
309                                                   309 
310         def build_reconfig(self, build_dir: st    310         def build_reconfig(self, build_dir: str, make_options: Optional[List[str]]) -> bool:
311                 """Creates a new .config if it    311                 """Creates a new .config if it is not a subset of the .kunitconfig."""
312                 kconfig_path = get_kconfig_pat    312                 kconfig_path = get_kconfig_path(build_dir)
313                 if not os.path.exists(kconfig_    313                 if not os.path.exists(kconfig_path):
314                         print('Generating .con    314                         print('Generating .config ...')
315                         return self.build_conf    315                         return self.build_config(build_dir, make_options)
316                                                   316 
317                 existing_kconfig = kunit_confi    317                 existing_kconfig = kunit_config.parse_file(kconfig_path)
318                 self._kconfig = self._ops.make    318                 self._kconfig = self._ops.make_arch_config(self._kconfig)
319                                                   319 
320                 if self._kconfig.is_subset_of(    320                 if self._kconfig.is_subset_of(existing_kconfig) and not self._kunitconfig_changed(build_dir):
321                         return True               321                         return True
322                 print('Regenerating .config ..    322                 print('Regenerating .config ...')
323                 os.remove(kconfig_path)           323                 os.remove(kconfig_path)
324                 return self.build_config(build    324                 return self.build_config(build_dir, make_options)
325                                                   325 
326         def build_kernel(self, jobs: int, buil    326         def build_kernel(self, jobs: int, build_dir: str, make_options: Optional[List[str]]) -> bool:
327                 try:                              327                 try:
328                         self._ops.make_olddefc    328                         self._ops.make_olddefconfig(build_dir, make_options)
329                         self._ops.make(jobs, b    329                         self._ops.make(jobs, build_dir, make_options)
330                 except (ConfigError, BuildErro    330                 except (ConfigError, BuildError) as e:
331                         logging.error(e)          331                         logging.error(e)
332                         return False              332                         return False
333                 return self.validate_config(bu    333                 return self.validate_config(build_dir)
334                                                   334 
335         def run_kernel(self, args: Optional[Li    335         def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', filter: str='', filter_action: Optional[str]=None, timeout: Optional[int]=None) -> Iterator[str]:
336                 if not args:                      336                 if not args:
337                         args = []                 337                         args = []
338                 if filter_glob:                   338                 if filter_glob:
339                         args.append('kunit.fil    339                         args.append('kunit.filter_glob=' + filter_glob)
340                 if filter:                        340                 if filter:
341                         args.append('kunit.fil    341                         args.append('kunit.filter="' + filter + '"')
342                 if filter_action:                 342                 if filter_action:
343                         args.append('kunit.fil    343                         args.append('kunit.filter_action=' + filter_action)
344                 args.append('kunit.enable=1')     344                 args.append('kunit.enable=1')
345                                                   345 
346                 process = self._ops.start(args    346                 process = self._ops.start(args, build_dir)
347                 assert process.stdout is not N    347                 assert process.stdout is not None  # tell mypy it's set
348                                                   348 
349                 # Enforce the timeout in a bac    349                 # Enforce the timeout in a background thread.
350                 def _wait_proc() -> None:         350                 def _wait_proc() -> None:
351                         try:                      351                         try:
352                                 process.wait(t    352                                 process.wait(timeout=timeout)
353                         except Exception as e:    353                         except Exception as e:
354                                 print(e)          354                                 print(e)
355                                 process.termin    355                                 process.terminate()
356                                 process.wait()    356                                 process.wait()
357                 waiter = threading.Thread(targ    357                 waiter = threading.Thread(target=_wait_proc)
358                 waiter.start()                    358                 waiter.start()
359                                                   359 
360                 output = open(get_outfile_path    360                 output = open(get_outfile_path(build_dir), 'w')
361                 try:                              361                 try:
362                         # Tee the output to th    362                         # Tee the output to the file and to our caller in real time.
363                         for line in process.st    363                         for line in process.stdout:
364                                 output.write(l    364                                 output.write(line)
365                                 yield line        365                                 yield line
366                 # This runs even if our caller    366                 # This runs even if our caller doesn't consume every line.
367                 finally:                          367                 finally:
368                         # Flush any leftover o    368                         # Flush any leftover output to the file
369                         output.write(process.s    369                         output.write(process.stdout.read())
370                         output.close()            370                         output.close()
371                         process.stdout.close()    371                         process.stdout.close()
372                                                   372 
373                         waiter.join()             373                         waiter.join()
374                         subprocess.call(['stty    374                         subprocess.call(['stty', 'sane'])
375                                                   375 
376         def signal_handler(self, unused_sig: i    376         def signal_handler(self, unused_sig: int, unused_frame: Optional[FrameType]) -> None:
377                 logging.error('Build interrupt    377                 logging.error('Build interruption occurred. Cleaning console.')
378                 subprocess.call(['stty', 'sane    378                 subprocess.call(['stty', 'sane'])
                                                      

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