]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - tools/testing/kunit/kunit_kernel.py
Merge tag 'asoc-v5.7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[mirror_ubuntu-hirsute-kernel.git] / tools / testing / kunit / kunit_kernel.py
CommitLineData
6ebf5866
FG
1# SPDX-License-Identifier: GPL-2.0
2#
3# Runs UML kernel, collects output, and handles errors.
4#
5# Copyright (C) 2019, Google LLC.
6# Author: Felix Guo <felixguoxiuping@gmail.com>
7# Author: Brendan Higgins <brendanhiggins@google.com>
8
9
10import logging
11import subprocess
12import os
13
14import kunit_config
15
16KCONFIG_PATH = '.config'
14ee5cfd 17kunitconfig_path = '.kunitconfig'
6ebf5866
FG
18
19class ConfigError(Exception):
20 """Represents an error trying to configure the Linux kernel."""
21
22
23class BuildError(Exception):
24 """Represents an error trying to build the Linux kernel."""
25
26
27class LinuxSourceTreeOperations(object):
28 """An abstraction over command line operations performed on a source tree."""
29
30 def make_mrproper(self):
31 try:
32 subprocess.check_output(['make', 'mrproper'])
33 except OSError as e:
34 raise ConfigError('Could not call make command: ' + e)
35 except subprocess.CalledProcessError as e:
36 raise ConfigError(e.output)
37
38 def make_olddefconfig(self, build_dir):
39 command = ['make', 'ARCH=um', 'olddefconfig']
40 if build_dir:
41 command += ['O=' + build_dir]
42 try:
43 subprocess.check_output(command)
44 except OSError as e:
45 raise ConfigError('Could not call make command: ' + e)
46 except subprocess.CalledProcessError as e:
47 raise ConfigError(e.output)
48
49 def make(self, jobs, build_dir):
50 command = ['make', 'ARCH=um', '--jobs=' + str(jobs)]
51 if build_dir:
52 command += ['O=' + build_dir]
53 try:
54 subprocess.check_output(command)
55 except OSError as e:
56 raise BuildError('Could not call execute make: ' + e)
57 except subprocess.CalledProcessError as e:
58 raise BuildError(e.output)
59
60 def linux_bin(self, params, timeout, build_dir):
61 """Runs the Linux UML binary. Must be named 'linux'."""
62 linux_bin = './linux'
63 if build_dir:
64 linux_bin = os.path.join(build_dir, 'linux')
65 process = subprocess.Popen(
66 [linux_bin] + params,
67 stdin=subprocess.PIPE,
68 stdout=subprocess.PIPE,
69 stderr=subprocess.PIPE)
70 process.wait(timeout=timeout)
71 return process
72
73
74def get_kconfig_path(build_dir):
75 kconfig_path = KCONFIG_PATH
76 if build_dir:
77 kconfig_path = os.path.join(build_dir, KCONFIG_PATH)
78 return kconfig_path
79
80class LinuxSourceTree(object):
81 """Represents a Linux kernel source tree with KUnit tests."""
82
83 def __init__(self):
84 self._kconfig = kunit_config.Kconfig()
e3212513 85 self._kconfig.read_from_file(kunitconfig_path)
6ebf5866
FG
86 self._ops = LinuxSourceTreeOperations()
87
88 def clean(self):
89 try:
90 self._ops.make_mrproper()
91 except ConfigError as e:
92 logging.error(e)
93 return False
94 return True
95
dde54b94
HF
96 def validate_config(self, build_dir):
97 kconfig_path = get_kconfig_path(build_dir)
98 validated_kconfig = kunit_config.Kconfig()
99 validated_kconfig.read_from_file(kconfig_path)
100 if not self._kconfig.is_subset_of(validated_kconfig):
101 invalid = self._kconfig.entries() - validated_kconfig.entries()
102 message = 'Provided Kconfig is not contained in validated .config. Following fields found in kunitconfig, ' \
103 'but not in .config: %s' % (
104 ', '.join([str(e) for e in invalid])
105 )
106 logging.error(message)
107 return False
108 return True
109
6ebf5866
FG
110 def build_config(self, build_dir):
111 kconfig_path = get_kconfig_path(build_dir)
112 if build_dir and not os.path.exists(build_dir):
113 os.mkdir(build_dir)
114 self._kconfig.write_to_file(kconfig_path)
115 try:
116 self._ops.make_olddefconfig(build_dir)
117 except ConfigError as e:
118 logging.error(e)
119 return False
dde54b94 120 return self.validate_config(build_dir)
6ebf5866
FG
121
122 def build_reconfig(self, build_dir):
14ee5cfd 123 """Creates a new .config if it is not a subset of the .kunitconfig."""
6ebf5866
FG
124 kconfig_path = get_kconfig_path(build_dir)
125 if os.path.exists(kconfig_path):
126 existing_kconfig = kunit_config.Kconfig()
127 existing_kconfig.read_from_file(kconfig_path)
128 if not self._kconfig.is_subset_of(existing_kconfig):
129 print('Regenerating .config ...')
130 os.remove(kconfig_path)
131 return self.build_config(build_dir)
132 else:
133 return True
134 else:
135 print('Generating .config ...')
136 return self.build_config(build_dir)
137
138 def build_um_kernel(self, jobs, build_dir):
139 try:
140 self._ops.make_olddefconfig(build_dir)
141 self._ops.make(jobs, build_dir)
142 except (ConfigError, BuildError) as e:
143 logging.error(e)
144 return False
dde54b94 145 return self.validate_config(build_dir)
6ebf5866 146
609952c2 147 def run_kernel(self, args=[], timeout=None, build_dir=''):
6ebf5866
FG
148 args.extend(['mem=256M'])
149 process = self._ops.linux_bin(args, timeout, build_dir)
609952c2 150 with open(os.path.join(build_dir, 'test.log'), 'w') as f:
6ebf5866
FG
151 for line in process.stdout:
152 f.write(line.rstrip().decode('ascii') + '\n')
153 yield line.rstrip().decode('ascii')