test-userland: rename to test-userland-full-system and port to LkmcCliFunction

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-01-22 00:00:00 +00:00
parent e51ec2aca9
commit c64e96e575
13 changed files with 119 additions and 79 deletions

View File

@@ -2467,7 +2467,7 @@ asdf=qwer
Source: link:userland/init_env_poweroff.c[].
==== init environment args
==== init arguments
The annoying dash `-` gets passed as a parameter to `init`, which makes it impossible to use this method for most non custom executables.
@@ -2488,6 +2488,8 @@ ab
so see how `a.b` is gone.
The simple workaround is to just create a shell script that does it, e.g. as we've done at: link:rootfs_overlay/gem5_exit.sh[].
==== init environment env
Wait, where do `HOME` and `TERM` come from? (greps the kernel). Ah, OK, the kernel sets those by default: https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/init/main.c#L173
@@ -11886,11 +11888,16 @@ This directory is copied into the target filesystem by:
....
./copy-overlay
./build-buildroot
....
Source link:copy-overlay[]
Source: link:copy-overlay[]
Since this directory does not require compilation, we also make it <<9p>> available to the guest directly even without `copy-overlay` at:
`copy-overlay` by itself, only places the files into our intermediate `./getenv out_rootfs_overlay_dir` directory.
This directory combines files from several sources, including for example link:build-userland[], which the final `./build-buildroot` puts into the root filesystem.
Since the link:rootfs_overlay[] directory does not require compilation, unlike say link:userland[] we also make it <<9p>> available to the guest directly even without `copy-overlay` at:
....
ls /mnt/9p/rootfs_overlay
@@ -11900,10 +11907,6 @@ This way you can just hack away the scripts and try them out immediately without
To add those scripts to the Buildroot root filesystem, you will need to run:
....
./build-buildroot
....
We could add that directory to `BR2_ROOTFS_OVERLAY` but we don't do this because this mechanism:
* also works for non Buildroot root filesystesms
@@ -11915,7 +11918,7 @@ and maintaining `BR2_ROOTFS_OVERLAY` in addition to our mechanism would duplicat
==== Automated tests
Run absolutely all tests:
Run almost all tests:
....
./build-test --size 3 && \
@@ -11929,15 +11932,20 @@ Sources:
* link:build-test[]
* link:test[]
* link:test-userland[]
* <<user-mode-tests>>
* <<baremetal-tests>>
This is not all tests, because there are too many possible variations and that would take forever.
Instead, we currently select on magic arch, currently `aarch64`, and for that arch run more stuff than on others.
We could in the future we will add an option to select the large arch, or do something smarter.
This full testing takes too much time to be feasible for every patch, but it should be done for every release.
See the sources of those test scripts to learn how to run more specialized tests.
One important tip is that you can select multiple archs and emulators of interest with a command such as:
One important tip is that you can select multiple archs and emulators of interest with any command as in:
....
./test-user-mode \
@@ -11958,7 +11966,21 @@ Test that the Internet works:
./run --arch x86_64 --kernel-cli '- lkmc_eval="ifup -a;wget -S google.com;poweroff;"'
....
Source: link:rootfs_overlay/test_all.sh[].
===== Test userland in full system
Run all userland tests from inside full system simulation (i.e. not <<user-mode-simulation>>):
....
./test-userland-full-system
....
This includes, in particular, userland programs that test the kernel modules, which cannot be tested in user mode simulation.
Basically just boots and runs: link:rootfs_overlay/test_all.sh[]
Failure is detected by looking for the <<magic-failure-string>>
Most userland programs that don't rely on kernel modules can also be tested in user mode simulation as explained at: <<user-mode-tests>>.
===== Test GDB
@@ -12037,7 +12059,7 @@ to the terminal, then our run scripts detect that and exit with status `1`.
This magic output string is notably used by:
* the `common_assert_fail()` function, which is used by <<baremetal-tests>>
* link:rootfs_overlay/test_fail.sh[], which is used by the link:test-userland[]
* link:rootfs_overlay/test_fail.sh[], which is used by <<test-userland-in-full-system>>
=== Bisection

View File

@@ -439,11 +439,15 @@ Valid emulators: {}
env['machine'] = 'VExpress_GEM5_V1'
else:
if not env['_args_given']['machine']:
# highmem=off needed since v3.0.0 due to:
# http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html
env['machine'] = 'virt,highmem=off'
if env['arch'] == 'aarch64':
env['machine'] += ',gic_version=3'
env['machine'] = 'virt'
if env['arch'] == 'arm':
# highmem=off needed since v3.0.0 due to:
# http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html
env['machine2'] = 'highmem=off'
elif env['arch'] == 'aarch64':
env['machine2'] = 'gic_version=3'
else:
env['machine2'] = None
# Buildroot
env['buildroot_build_dir'] = join(env['buildroot_out_dir'], 'build', env['buildroot_build_id'], env['arch'])
@@ -556,7 +560,7 @@ Valid emulators: {}
env['trace_txt_file'] = env['qemu_trace_txt_file']
env['run_cmd_file'] = join(env['run_dir'], 'run.sh')
# Linux kernl.
# Linux kernel.
if not env['_args_given']['linux_build_dir']:
env['linux_build_dir'] = join(env['out_dir'], 'linux', env['linux_build_id'], env['arch'])
env['lkmc_vmlinux'] = join(env['linux_build_dir'], 'vmlinux')
@@ -577,6 +581,11 @@ Valid emulators: {}
else:
env['vmlinux'] = env['lkmc_vmlinux']
env['linux_image'] = env['lkmc_linux_image']
if env['emulator']== 'gem5':
env['userland_quit_cmd'] = '/gem5_exit.sh'
else:
env['userland_quit_cmd'] = '/poweroff.out'
env['quit_init'] = 'init={}'.format(env['userland_quit_cmd'])
# Kernel modules.
env['kernel_modules_build_dir'] = join(env['kernel_modules_build_base_dir'], env['arch'])
@@ -1043,7 +1052,19 @@ class Test:
return ' '.join(out)
class TestCliFunction(LkmcCliFunction):
'''
Represents a CLI command that runs tests.
Automates test reporting boilerplate for those commands.
'''
def __init__(self, *args, **kwargs):
defaults = {
'print_time': False,
}
if 'defaults' in kwargs:
defaults.update(kwargs['defaults'])
kwargs['defaults'] = defaults
super().__init__(*args, **kwargs)
self.tests = []
self.add_argument(
@@ -1054,13 +1075,25 @@ Stop running at the first failed test.
'''
)
def run_test(self, run_obj, run_args, extra_params):
test_id_string = self.test_setup(extra_params)
def run_test(self, run_obj, run_args, test_id=None):
'''
This is a setup / run / teardown setup for simple tests that just do a single run.
More complex tests might need to run the steps separately, e.g. gdb tests
must run multiple commands: one for the run and one GDB.
:param run_obj: callable object
:param run_args: arguments to be passed to the runnable object
:param test_id: test identifier, to be added in addition to of arch and emulator ids
'''
test_id_string = self.test_setup(test_id)
exit_status = run_obj(**run_args)
self.test_teardown(run_obj, exit_status, test_id_string)
def test_setup(self, extra_params):
test_id_string = '{} {} {}'.format(self.env['emulator'], self.env['arch'], extra_params)
def test_setup(self, test_id):
test_id_string = '{} {}'.format(self.env['emulator'], self.env['arch'])
if test_id is not None:
test_id_string += ' {}'.format(test_id)
self.log_info('test_id {}'.format(test_id_string), flush=True)
return test_id_string

View File

@@ -13,7 +13,6 @@ class Main(common.BuildCliFunction):
description='''\
https://github.com/cirosantilli/linux-kernel-module-cheat#rootfs_overlay
''')
def build(self):
# TODO: print rsync equivalent, move into shell_helpers.
distutils.dir_util.copy_tree(

4
rootfs_overlay/gem5_exit.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
# To be able to do init=/gem5_exit.sh, since kernel CLI argument passing is too messy:
# https://github.com/cirosantilli/linux-kernel-module-cheat#init-arguments
m5 exit

10
run
View File

@@ -472,10 +472,20 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
.format(virtfs_dir=virtfs_dir, virtfs_tag=virtfs_tag),
LF,
])
if self.env['machine2'] is not None:
# Multiple -machine options can also be given comma separated in one -machine.
# We use multiple because the machine is used as an identifier on baremetal tests
# build paths, so better keep them clean.
machine2 = ['-machine', self.env['machine2'], LF]
else:
machine2 = []
cmd.extend(
[
qemu_executable, LF,
'-machine', self.env['machine'], LF,
] +
machine2 +
[
'-device', 'rtl8139,netdev=net0', LF,
'-gdb', 'tcp::{}'.format(self.env['gdb_port']), LF,
'-kernel', self.env['image'], LF,

2
test
View File

@@ -10,7 +10,7 @@ while [ $# -gt 0 ]; do
esac
done
./test-boot --size "$test_size"
./test-modules --all-archs --all-emulators
./test-userland --all-archs --all-emulators
./test-gdb --all-archs --all-emulators
./test-baremetal --all-archs --all-emulators
./test-user-mode --all-archs --all-emulators

View File

@@ -8,9 +8,6 @@ import common
class Main(common.TestCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
supported_archs=common.consts['crosstool_ng_supported_archs'],
)
self.add_argument(

View File

@@ -7,9 +7,6 @@ from shell_helpers import LF
class Main(common.TestCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
description='''\
Run Linux kernel boot tests and benchmarks.
'''
@@ -55,10 +52,7 @@ Size of the tests to run. Scale:
self.run = self.import_path_main('run')
self.common_args = self.get_common_args()
self.common_args['ctrl_c_host'] = True
if self.env['emulator'] == 'gem5':
self.common_args['eval'] = 'm5 exit'
elif self.env['emulator'] == 'qemu':
self.common_args['eval'] = '/poweroff.out'
self.common_args['kernel_cli'] = self.env['quit_init']
if (self.env['emulator'] == 'qemu' or
(self.env['emulator'] == 'gem5' and self.env['size'] >= 2)):
self._bench()

View File

@@ -7,11 +7,7 @@ import common
class Main(common.TestCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
)
super().__init__()
self.add_argument(
'tests',
nargs='*',

View File

@@ -8,9 +8,6 @@ import common
class Main(common.TestCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
description='''\
https://github.com/cirosantilli/linux-kernel-module-cheat#user-mode-tests
'''

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env python3
import os
import sys
import common
class Main(common.LkmcCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
description='''\
Boot Linux and run all non-interactive userland tests, including those
for kernel modules.
Detect failure based on the magic terminal failure string.
'''
)
def timed_main(self):
run = self.import_path_main('run')
run_args = self.get_common_args()
run_args['eval_after'] = '/test_all.sh;/poweroff.out'
run(**run_args)
if __name__ == '__main__':
Main().cli()

22
test-userland-full-system Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python3
import os
import sys
import common
class Main(common.TestCliFunction):
def __init__(self):
super().__init__(
description='''\
https://github.com/cirosantilli/linux-kernel-module-cheat#test-userland-in-full-system
'''
)
def timed_main(self):
run = self.import_path_main('run')
run_args = self.get_common_args()
run_args['eval_after'] = '/test_all.sh;{};'.format(self.env['userland_quit_cmd'])
self.run_test(run, run_args)
if __name__ == '__main__':
Main().cli()

View File

@@ -15,18 +15,13 @@ More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#t
def timed_main(self):
args = self.get_common_args()
run = self.import_path_main('run')
self.common_args['kernel_cli'] = self.env['quit_init']
if self.env['emulator'] == 'gem5':
args.update({
'eval': 'm5 exit',
'trace': 'Exec,-ExecSymbol,-ExecMicro',
})
args['trace'] = 'Exec,-ExecSymbol,-ExecMicro'
run.main(**args)
elif self.env['emulator'] == 'qemu':
run_args = args.copy()
run_args.update({
'kernel_cli': 'init=/poweroff.out',
'trace': 'exec_tb',
})
args['trace'] = 'exec_tb'
run.main(**run_args)
qemu_trace2txt = self.import_path_main('qemu-trace2txt')
qemu_trace2txt.main(**args)