Re: [RFC v2 3/4] kunit: tool: add support for QEMU
From: Daniel Latypov
Date: Thu Apr 29 2021 - 19:40:12 EST
On Thu, Apr 29, 2021 at 1:51 PM Brendan Higgins
<brendanhiggins@xxxxxxxxxx> wrote:
>
> Add basic support to run QEMU via kunit_tool. Add support for i386,
> x86_64, arm, arm64, and a bunch more.
Hmmm, I'm wondering if I'm seeing unrelated breakages.
Applied these patches on top of 55ba0fe059a5 ("Merge tag
'for-5.13-tag' of
git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux")
$ make mrproper
$ rm -rf .kunit/* # just in case
$ ./tools/testing/kunit/kunit.py run --arch=arm64
...
ERROR:root:arch/arm64/Makefile:25: ld does not support
--fix-cortex-a53-843419; kernel may be susceptible to erratum
arch/arm64/Makefile:44: Detected assembler with broken .inst;
disassembly will be unreliable
gcc: error: unrecognized command-line option ‘-mlittle-endian’
So it seems like my version of ld might be out of date, but my gcc is 10.2.1
Is there a minimum version of the toolchain this would expect that we
can call out in the commit message (and in the Documentation)?
--arch=x86_64 worked just fine for me, however, which is mainly what I
was interested in.
I've mainly just left some nits and comments regarding typechecking.
>
> Signed-off-by: Brendan Higgins <brendanhiggins@xxxxxxxxxx>
> ---
> tools/testing/kunit/kunit.py | 33 +++-
> tools/testing/kunit/kunit_config.py | 2 +-
> tools/testing/kunit/kunit_kernel.py | 207 +++++++++++++++++++++----
> tools/testing/kunit/kunit_tool_test.py | 15 +-
> 4 files changed, 217 insertions(+), 40 deletions(-)
>
> diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
> index d5144fcb03acd..07ef80062873b 100755
> --- a/tools/testing/kunit/kunit.py
> +++ b/tools/testing/kunit/kunit.py
> @@ -70,10 +70,10 @@ def build_tests(linux: kunit_kernel.LinuxSourceTree,
> kunit_parser.print_with_timestamp('Building KUnit Kernel ...')
>
> build_start = time.time()
> - success = linux.build_um_kernel(request.alltests,
> - request.jobs,
> - request.build_dir,
> - request.make_options)
> + success = linux.build_kernel(request.alltests,
> + request.jobs,
> + request.build_dir,
> + request.make_options)
> build_end = time.time()
> if not success:
> return KunitResult(KunitStatus.BUILD_FAILURE,
> @@ -187,6 +187,14 @@ def add_common_opts(parser) -> None:
> help='Path to Kconfig fragment that enables KUnit tests',
> metavar='kunitconfig')
>
> + parser.add_argument('--arch',
> + help='Specifies the architecture to run tests under.',
optional: perhaps add "(e.g. x86_64, um)"
Most people using this would be able to infer that, but I prefer
strings that are basically enums to document examples of useful
values.
(And x86 is probably the one most people want to use this flag for).
> + type=str, default='um', metavar='arch')
> +
> + parser.add_argument('--cross_compile',
> + help='Sets make\'s CROSS_COMPILE variable.',
> + metavar='cross_compile')
> +
> def add_build_opts(parser) -> None:
> parser.add_argument('--jobs',
> help='As in the make command, "Specifies the number of '
> @@ -268,7 +276,10 @@ def main(argv, linux=None):
> os.mkdir(cli_args.build_dir)
>
> if not linux:
> - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig)
> + linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
> + kunitconfig_path=cli_args.kunitconfig,
> + arch=cli_args.arch,
> + cross_compile=cli_args.cross_compile)
>
> request = KunitRequest(cli_args.raw_output,
> cli_args.timeout,
> @@ -287,7 +298,9 @@ def main(argv, linux=None):
> os.mkdir(cli_args.build_dir)
>
> if not linux:
> - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig)
> + linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
> + kunitconfig_path=cli_args.kunitconfig,
> + arch=cli_args.arch)
>
> request = KunitConfigRequest(cli_args.build_dir,
> cli_args.make_options)
> @@ -299,7 +312,9 @@ def main(argv, linux=None):
> sys.exit(1)
> elif cli_args.subcommand == 'build':
> if not linux:
> - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig)
> + linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
> + kunitconfig_path=cli_args.kunitconfig,
> + arch=cli_args.arch)
>
> request = KunitBuildRequest(cli_args.jobs,
> cli_args.build_dir,
> @@ -313,7 +328,9 @@ def main(argv, linux=None):
> sys.exit(1)
> elif cli_args.subcommand == 'exec':
> if not linux:
> - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir)
> + linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
> + kunitconfig_path=cli_args.kunitconfig,
> + arch=cli_args.arch)
>
> exec_request = KunitExecRequest(cli_args.timeout,
> cli_args.build_dir,
> diff --git a/tools/testing/kunit/kunit_config.py b/tools/testing/kunit/kunit_config.py
> index 1e2683dcc0e7a..07d76be392544 100644
> --- a/tools/testing/kunit/kunit_config.py
> +++ b/tools/testing/kunit/kunit_config.py
> @@ -53,7 +53,7 @@ class Kconfig(object):
> return True
>
> def write_to_file(self, path: str) -> None:
> - with open(path, 'w') as f:
> + with open(path, 'a+') as f:
I might be missing something, but do we need this?
w => a means we wouldn't truncate the file if it exists. I can imagine
I'm missing something that makes it necessary.
+ => opens for read/write: we don't do any reads with f afaict.
> for entry in self.entries():
> f.write(str(entry) + '\n')
>
> diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
> index 7d5b77967d48f..b8b3b76aaa17e 100644
> --- a/tools/testing/kunit/kunit_kernel.py
> +++ b/tools/testing/kunit/kunit_kernel.py
> @@ -15,6 +15,8 @@ from typing import Iterator
>
> from contextlib import ExitStack
>
> +from collections import namedtuple
> +
> import kunit_config
> import kunit_parser
>
> @@ -40,6 +42,10 @@ class BuildError(Exception):
> class LinuxSourceTreeOperations(object):
> """An abstraction over command line operations performed on a source tree."""
>
> + def __init__(self, linux_arch, cross_compile):
nit: let's annotate these as `linux_arch: str, cross_compile: str` (or
is it Optional[str] here?)
I can see a reader thinking arch might be an enum and that
cross_compile might be a bool.
> + self._linux_arch = linux_arch
> + self._cross_compile = cross_compile
> +
> def make_mrproper(self) -> None:
> try:
> subprocess.check_output(['make', 'mrproper'], stderr=subprocess.STDOUT)
> @@ -48,12 +54,18 @@ class LinuxSourceTreeOperations(object):
> except subprocess.CalledProcessError as e:
> raise ConfigError(e.output.decode())
>
> + def make_arch_qemuconfig(self, build_dir):
> + pass
> +
> def make_olddefconfig(self, build_dir, make_options) -> None:
> - command = ['make', 'ARCH=um', 'olddefconfig']
> + command = ['make', 'ARCH=' + self._linux_arch, 'olddefconfig']
> + if self._cross_compile:
> + command += ['CROSS_COMPILE=' + self._cross_compile]
> if make_options:
> command.extend(make_options)
> if build_dir:
> command += ['O=' + build_dir]
> + print(' '.join(command))
> try:
> subprocess.check_output(command, stderr=subprocess.STDOUT)
> except OSError as e:
> @@ -61,6 +73,154 @@ class LinuxSourceTreeOperations(object):
> except subprocess.CalledProcessError as e:
> raise ConfigError(e.output.decode())
>
> + def make(self, jobs, build_dir, make_options) -> None:
> + command = ['make', 'ARCH=' + self._linux_arch, '--jobs=' + str(jobs)]
> + if make_options:
> + command.extend(make_options)
> + if self._cross_compile:
> + command += ['CROSS_COMPILE=' + self._cross_compile]
> + if build_dir:
> + command += ['O=' + build_dir]
> + print(' '.join(command))
> + try:
> + proc = subprocess.Popen(command,
> + stderr=subprocess.PIPE,
> + stdout=subprocess.DEVNULL)
> + except OSError as e:
> + raise BuildError('Could not call execute make: ' + e)
pytype complains about this.
You'd want `+ str(e)`
> + except subprocess.CalledProcessError as e:
> + raise BuildError(e.output)
> + _, stderr = proc.communicate()
> + if proc.returncode != 0:
> + raise BuildError(stderr.decode())
> + if stderr: # likely only due to build warnings
> + print(stderr.decode())
> +
> + def run(self, params, timeout, build_dir, outfile) -> None:
> + pass
> +
> +
> +QemuArchParams = namedtuple('QemuArchParams', ['linux_arch',
> + 'qemuconfig',
> + 'qemu_arch',
> + 'kernel_path',
> + 'kernel_command_line',
> + 'extra_qemu_params'])
> +
> +
> +QEMU_ARCHS = {
> + 'i386' : QemuArchParams(linux_arch='i386',
> + qemuconfig='CONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y',
> + qemu_arch='x86_64',
> + kernel_path='arch/x86/boot/bzImage',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=['']),
> + 'x86_64' : QemuArchParams(linux_arch='x86_64',
> + qemuconfig='CONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y',
> + qemu_arch='x86_64',
> + kernel_path='arch/x86/boot/bzImage',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=['']),
> + 'arm' : QemuArchParams(linux_arch='arm',
> + qemuconfig='''CONFIG_ARCH_VIRT=y
> +CONFIG_SERIAL_AMBA_PL010=y
> +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
> +CONFIG_SERIAL_AMBA_PL011=y
> +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y''',
> + qemu_arch='arm',
> + kernel_path='arch/arm/boot/zImage',
> + kernel_command_line='console=ttyAMA0',
> + extra_qemu_params=['-machine virt']),
> + 'arm64' : QemuArchParams(linux_arch='arm64',
> + qemuconfig='''CONFIG_SERIAL_AMBA_PL010=y
> +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
> +CONFIG_SERIAL_AMBA_PL011=y
> +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y''',
> + qemu_arch='aarch64',
> + kernel_path='arch/arm64/boot/Image.gz',
> + kernel_command_line='console=ttyAMA0',
> + extra_qemu_params=['-machine virt', '-cpu cortex-a57']),
> + 'alpha' : QemuArchParams(linux_arch='alpha',
> + qemuconfig='CONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y',
> + qemu_arch='alpha',
> + kernel_path='arch/alpha/boot/vmlinux',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=['']),
> + 'powerpc' : QemuArchParams(linux_arch='powerpc',
> + qemuconfig='CONFIG_PPC64=y\nCONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y\nCONFIG_HVC_CONSOLE=y',
> + qemu_arch='ppc64',
> + kernel_path='vmlinux',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=['-M pseries', '-cpu power8']),
> + 'riscv' : QemuArchParams(linux_arch='riscv',
> + qemuconfig='CONFIG_SOC_VIRT=y\nCONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y\nCONFIG_SERIAL_OF_PLATFORM=y\nCONFIG_SERIAL_EARLYCON_RISCV_SBI=y',
> + qemu_arch='riscv64',
> + kernel_path='arch/riscv/boot/Image',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=['-machine virt', '-cpu rv64', '-bios opensbi-riscv64-generic-fw_dynamic.bin']),
> + 's390' : QemuArchParams(linux_arch='s390',
> + qemuconfig='CONFIG_EXPERT=y\nCONFIG_TUNE_ZEC12=y\nCONFIG_NUMA=y\nCONFIG_MODULES=y',
> + qemu_arch='s390x',
> + kernel_path='arch/s390/boot/bzImage',
> + kernel_command_line='console=ttyS0',
> + extra_qemu_params=[
> + '-machine s390-ccw-virtio',
> + '-cpu qemu',]),
> + 'sparc' : QemuArchParams(linux_arch='sparc',
> + qemuconfig='CONFIG_SERIAL_8250=y\nCONFIG_SERIAL_8250_CONSOLE=y',
> + qemu_arch='sparc',
> + kernel_path='arch/sparc/boot/zImage',
> + kernel_command_line='console=ttyS0 mem=256M',
> + extra_qemu_params=['-m 256']),
> +}
Oh my.
I don't know enough to say if there's a better way of doing this.
But I think we should probably split this out into a separate python
file, if this mapping remains necessary.
E.g. in a qemu_configs.py file or the like.
> +
> +class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
I've called out the two errors pytype gives already, but mypy is even
worse about this new class :(
$ mypy tools/testing/kunit/*.py
tools/testing/kunit/kunit_kernel.py:90: error: Unsupported operand
types for + ("str" and "OSError")
tools/testing/kunit/kunit_kernel.py:278: error: Incompatible types in
assignment (expression has type "LinuxSourceTreeOperationsQemu",
variable has type "Optional[LinuxSourceTreeOperationsUml]")
tools/testing/kunit/kunit_kernel.py:298: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_mrproper"
tools/testing/kunit/kunit_kernel.py:324: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_arch_qemuconfig"
tools/testing/kunit/kunit_kernel.py:325: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_olddefconfig"
tools/testing/kunit/kunit_kernel.py:352: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_allyesconfig"
tools/testing/kunit/kunit_kernel.py:353: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_arch_qemuconfig"
tools/testing/kunit/kunit_kernel.py:354: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute
"make_olddefconfig"
tools/testing/kunit/kunit_kernel.py:355: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute "make"
tools/testing/kunit/kunit_kernel.py:368: error: Item "None" of
"Optional[LinuxSourceTreeOperationsUml]" has no attribute "run"
So to make up for mypy being less smart, we can do this and get it down 2 errors
diff --git a/tools/testing/kunit/kunit_kernel.py
b/tools/testing/kunit/kunit_kernel.py
index b8b3b76aaa17..a0aaa28db4c1 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -11,7 +11,7 @@ import subprocess
import os
import shutil
import signal
-from typing import Iterator
+from typing import Iterator, Union
from contextlib import ExitStack
@@ -269,15 +269,16 @@ class LinuxSourceTree(object):
def __init__(self, build_dir: str, load_config=True,
kunitconfig_path='', arch=None, cross_compile=None) -> None:
signal.signal(signal.SIGINT, self.signal_handler)
- self._ops = None
+ ops = None # type: Union[None,
LinuxSourceTreeOperationsUml, LinuxSourceTreeOperationsQemu]
if arch is None or arch == 'um':
self._arch = 'um'
- self._ops = LinuxSourceTreeOperationsUml()
+ ops = LinuxSourceTreeOperationsUml()
elif arch in QEMU_ARCHS:
self._arch = arch
- self._ops =
LinuxSourceTreeOperationsQemu(QEMU_ARCHS[arch],
cross_compile=cross_compile)
+ ops =
LinuxSourceTreeOperationsQemu(QEMU_ARCHS[arch],
cross_compile=cross_compile)
else:
raise ConfigError(arch + ' is not a valid arch')
+ self._ops = ops
if not load_config:
return
> +
> + def __init__(self, qemu_arch_params, cross_compile):
> + super().__init__(linux_arch=qemu_arch_params.linux_arch,
> + cross_compile=cross_compile)
> + self._qemuconfig = qemu_arch_params.qemuconfig
> + self._qemu_arch = qemu_arch_params.qemu_arch
> + self._kernel_path = qemu_arch_params.kernel_path
> + print(self._kernel_path)
looks like a leftover debugging print statement?
> + self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot'
> + self._extra_qemu_params = qemu_arch_params.extra_qemu_params
> +
> + def make_arch_qemuconfig(self, build_dir):
> + qemuconfig = kunit_config.Kconfig()
> + qemuconfig.parse_from_string(self._qemuconfig)
> + qemuconfig.write_to_file(get_kconfig_path(build_dir))
> +
> + def run(self, params, timeout, build_dir, outfile):
> + kernel_path = os.path.join(build_dir, self._kernel_path)
> + qemu_command = ['qemu-system-' + self._qemu_arch,
> + '-nodefaults',
> + '-m', '1024',
> + '-kernel', kernel_path,
> + '-append', '\'' + ' '.join(params + [self._kernel_command_line]) + '\'',
> + '-no-reboot',
> + '-nographic',
> + '-serial stdio'] + self._extra_qemu_params
> + print(' '.join(qemu_command))
ditto, a debug statement?
Though this one could be useful to actually print out for the user if
we include some more context in the message.
> + with open(outfile, 'w') as output:
> + process = subprocess.Popen(' '.join(qemu_command),
> + stdin=subprocess.PIPE,
> + stdout=output,
> + stderr=subprocess.STDOUT,
> + text=True, shell=True)
> + try:
> + process.wait(timeout=timeout)
> + except Exception as e:
> + print(e)
> + process.terminate()
> + return process
> +
> +class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations):
> + """An abstraction over command line operations performed on a source tree."""
> +
> + def __init__(self):
> + super().__init__(linux_arch='um', cross_compile=None)
> +
> def make_allyesconfig(self, build_dir, make_options) -> None:
> kunit_parser.print_with_timestamp(
> 'Enabling all CONFIGs for UML...')
> @@ -83,32 +243,16 @@ class LinuxSourceTreeOperations(object):
> kunit_parser.print_with_timestamp(
> 'Starting Kernel with all configs takes a few minutes...')
>
> - def make(self, jobs, build_dir, make_options) -> None:
> - command = ['make', 'ARCH=um', '--jobs=' + str(jobs)]
> - if make_options:
> - command.extend(make_options)
> - if build_dir:
> - command += ['O=' + build_dir]
> - try:
> - proc = subprocess.Popen(command,
> - stderr=subprocess.PIPE,
> - stdout=subprocess.DEVNULL)
> - except OSError as e:
> - raise BuildError('Could not call make command: ' + str(e))
> - _, stderr = proc.communicate()
> - if proc.returncode != 0:
> - raise BuildError(stderr.decode())
> - if stderr: # likely only due to build warnings
> - print(stderr.decode())
> -
> - def linux_bin(self, params, timeout, build_dir) -> None:
> + def run(self, params, timeout, build_dir, outfile):
> """Runs the Linux UML binary. Must be named 'linux'."""
> linux_bin = get_file_path(build_dir, 'linux')
> outfile = get_outfile_path(build_dir)
> with open(outfile, 'w') as output:
> process = subprocess.Popen([linux_bin] + params,
> + stdin=subprocess.PIPE,
> stdout=output,
> - stderr=subprocess.STDOUT)
> + stderr=subprocess.STDOUT,
> + text=True)
> process.wait(timeout)
>
> def get_kconfig_path(build_dir) -> str:
> @@ -123,10 +267,17 @@ def get_outfile_path(build_dir) -> str:
> class LinuxSourceTree(object):
> """Represents a Linux kernel source tree with KUnit tests."""
>
> - def __init__(self, build_dir: str, load_config=True, kunitconfig_path='') -> None:
> + def __init__(self, build_dir: str, load_config=True, kunitconfig_path='', arch=None, cross_compile=None) -> None:
> signal.signal(signal.SIGINT, self.signal_handler)
> -
> - self._ops = LinuxSourceTreeOperations()
> + self._ops = None
> + if arch is None or arch == 'um':
> + self._arch = 'um'
> + self._ops = LinuxSourceTreeOperationsUml()
> + elif arch in QEMU_ARCHS:
> + self._arch = arch
> + self._ops = LinuxSourceTreeOperationsQemu(QEMU_ARCHS[arch], cross_compile=cross_compile)
> + else:
> + raise ConfigError(arch + ' is not a valid arch')
>
> if not load_config:
> return
> @@ -170,6 +321,7 @@ class LinuxSourceTree(object):
> os.mkdir(build_dir)
> self._kconfig.write_to_file(kconfig_path)
> try:
> + self._ops.make_arch_qemuconfig(build_dir)
> self._ops.make_olddefconfig(build_dir, make_options)
> except ConfigError as e:
> logging.error(e)
> @@ -192,10 +344,13 @@ class LinuxSourceTree(object):
> print('Generating .config ...')
> return self.build_config(build_dir, make_options)
>
> - def build_um_kernel(self, alltests, jobs, build_dir, make_options) -> bool:
> + def build_kernel(self, alltests, jobs, build_dir, make_options) -> bool:
> try:
> if alltests:
> + if self._arch != 'um':
> + raise ConfigError('Only the "um" arch is supported for alltests')
> self._ops.make_allyesconfig(build_dir, make_options)
Minor note: pytype doesn't like this.
The code is correct, but pytype can't figure out that ops can't be the
QEMU variant.
Pytype recognizes comments like " # pytype: disable=attribute-error"
but mypy doesn't.
So I don't know that there's a way we can make both of them happy :/
> + self._ops.make_arch_qemuconfig(build_dir)
> self._ops.make_olddefconfig(build_dir, make_options)
> self._ops.make(jobs, build_dir, make_options)
> except (ConfigError, BuildError) as e:
> @@ -209,8 +364,8 @@ class LinuxSourceTree(object):
> args.extend(['mem=1G', 'console=tty','kunit_shutdown=halt'])
> if filter_glob:
> args.append('kunit.filter_glob='+filter_glob)
> - self._ops.linux_bin(args, timeout, build_dir)
> outfile = get_outfile_path(build_dir)
> + self._ops.run(args, timeout, build_dir, outfile)
> subprocess.call(['stty', 'sane'])
> with open(outfile, 'r') as file:
> for line in file:
> diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
> index 1ad3049e90698..25e8be95a575d 100755
> --- a/tools/testing/kunit/kunit_tool_test.py
> +++ b/tools/testing/kunit/kunit_tool_test.py
> @@ -297,7 +297,7 @@ class KUnitMainTest(unittest.TestCase):
>
> self.linux_source_mock = mock.Mock()
> self.linux_source_mock.build_reconfig = mock.Mock(return_value=True)
> - self.linux_source_mock.build_um_kernel = mock.Mock(return_value=True)
> + self.linux_source_mock.build_kernel = mock.Mock(return_value=True)
> self.linux_source_mock.run_kernel = mock.Mock(return_value=all_passed_log)
>
> def test_config_passes_args_pass(self):
> @@ -308,7 +308,7 @@ class KUnitMainTest(unittest.TestCase):
> def test_build_passes_args_pass(self):
> kunit.main(['build'], self.linux_source_mock)
> self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 0)
> - self.linux_source_mock.build_um_kernel.assert_called_once_with(False, 8, '.kunit', None)
> + self.linux_source_mock.build_kernel.assert_called_once_with(False, 8, '.kunit', None)
> self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0)
>
> def test_exec_passes_args_pass(self):
> @@ -390,7 +390,7 @@ class KUnitMainTest(unittest.TestCase):
> def test_build_builddir(self):
> build_dir = '.kunit'
> kunit.main(['build', '--build_dir', build_dir], self.linux_source_mock)
> - self.linux_source_mock.build_um_kernel.assert_called_once_with(False, 8, build_dir, None)
> + self.linux_source_mock.build_kernel.assert_called_once_with(False, 8, build_dir, None)
>
> def test_exec_builddir(self):
> build_dir = '.kunit'
> @@ -404,14 +404,19 @@ class KUnitMainTest(unittest.TestCase):
> mock_linux_init.return_value = self.linux_source_mock
> kunit.main(['run', '--kunitconfig=mykunitconfig'])
> # Just verify that we parsed and initialized it correctly here.
> - mock_linux_init.assert_called_once_with('.kunit', kunitconfig_path='mykunitconfig')
> + mock_linux_init.assert_called_once_with('.kunit',
> + kunitconfig_path='mykunitconfig',
> + arch='um',
> + cross_compile=None)
>
> @mock.patch.object(kunit_kernel, 'LinuxSourceTree')
> def test_config_kunitconfig(self, mock_linux_init):
> mock_linux_init.return_value = self.linux_source_mock
> kunit.main(['config', '--kunitconfig=mykunitconfig'])
> # Just verify that we parsed and initialized it correctly here.
> - mock_linux_init.assert_called_once_with('.kunit', kunitconfig_path='mykunitconfig')
> + mock_linux_init.assert_called_once_with('.kunit',
> + kunitconfig_path='mykunitconfig',
> + arch='um')
>
> if __name__ == '__main__':
> unittest.main()
> --
> 2.31.1.498.g6c1eba8ee3d-goog
>