test-modules: convert to use LkmcCliFunction

This commit is contained in:
Ciro Santilli
2019-01-22 00:00:00 +00:00
committed by Ciro Santilli 六四事件 法轮功
parent 4a92813252
commit 718941f3cf
8 changed files with 112 additions and 77 deletions

View File

@@ -3159,15 +3159,17 @@ Result on <<p51>> at bad30f513c46c1b0995d3a10c0d9bc2a33dc4fa0:
=== User mode tests
Automatically run non-interactive userland tests that don't depend on any kernel modules:
Automatically run non-interactive userland tests that can be run in user mode simulation:
....
./build-userland --all-archs --all-emulators
./build-userland --all-archs --all-emulators --static --userland-build-id static
./test-userland --all-archs --all-emulators
./test-user-mode --all-archs --all-emulators
....
Source: link:test-userland[]
Source: link:test-user-mode[]
This testing excludes notably kernel module tests which depend on a full running kernel.
The gem5 tests require building statically with build id `static`, see also: <<gem5-syscall-emulation-mode>>. TODO automate this better.
@@ -11696,11 +11698,11 @@ They contain data structs and magic constant for kernel to userland communicatio
Userland test programs. They can be used in the following ways:
* inside a full system simulation
* inside a full system simulation, e.g.: <<qemu-buildroot-setup>>
* inside <<user-mode-simulation>>
* directly on the host
* directly on the host: <<userland-directory-host-build>>
For usage inside full system, first ensure that Buildroot has been built for the toolchain, and then build the examples with:
For usage inside full system simulation, first ensure that Buildroot has been built for the toolchain, and then build the examples with:
....
./build-userland
@@ -11898,7 +11900,7 @@ Sources:
* link:build-test[]
* link:test[]
* link:test-modules[]
* link:test-userland[]
* <<user-mode-tests>>
* <<baremetal-tests>>
@@ -11909,7 +11911,7 @@ 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:
....
./test-userland \
./test-user-mode \
--arch x86_64 \
--arch aarch64 \
--emulator gem5 \

View File

@@ -1,25 +1,27 @@
#!/bin/sh
test_dir="${1:-.}"
for test in \
/anonymous_inode.sh \
/character_device.sh \
/character_device_create.sh \
/debugfs.sh \
/dep.sh \
/fops.sh \
/init_module.sh \
/ioctl.sh \
/kstrto.sh \
/mmap.sh \
/netlink.sh \
/params.sh \
/procfs.sh \
/seq_file.sh \
/seq_file_single_open.sh \
/sysfs.sh \
anonymous_inode.sh \
character_device.sh \
character_device_create.sh \
debugfs.sh \
dep.sh \
fops.sh \
init_module.sh \
ioctl.sh \
kstrto.sh \
mmap.sh \
netlink.sh \
params.sh \
procfs.sh \
seq_file.sh \
seq_file_single_open.sh \
sysfs.sh \
; do
if ! "$test"; then
echo "lkmc_test_fail: ${test}"
if ! "${test_dir}/${test}"; then
echo "Test failed: ${test}"
test_fail.sh
exit 1
fi
done
echo lkmc_test_pass
echo 'All tests passed.'

4
rootfs_overlay/test_fail.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
# Print the magic fail string that our scripts detect
# as a simulation failure.
echo lkmc_test_fail

7
run
View File

@@ -618,9 +618,10 @@ Run QEMU with VNC instead of the default SDL. Connect to it with:
if not self.env['userland']:
if os.path.exists(self.env['guest_terminal_file']):
with open(self.env['guest_terminal_file'], 'br') as logfile:
lines = logfile.readlines()
if lines and lines[-1].rstrip() == self.env['magic_fail_string']:
exit_status = 1
for line in logfile.readlines():
if line.rstrip() == self.env['magic_fail_string']:
exit_status = 1
break
if exit_status != 0:
self.log_error('simulation error detected by parsing logs')
return exit_status

4
test
View File

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

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -eu
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
getvar="${root_dir}/getvar"
termout_file="$("$getvar" termout_file)"
./run --eval-busybox '/test_all.sh;/poweroff.out' --kvm
grep -q lkmc_test_pass "$termout_file"

64
test-user-mode Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
import os
import sys
import common
class Main(common.LkmcCliFunction):
def __init__(self):
super().__init__(
defaults={
'print_time': False,
},
description='''\
https://github.com/cirosantilli/linux-kernel-module-cheat#user-mode-tests
'''
,
)
self.add_argument(
'tests',
nargs='*',
help='''\
If given, run only the given tests. Otherwise, run all tests.
'''
)
def timed_main(self):
run = self.import_path_main('run')
run_args = self.get_common_args()
if self.env['emulator'] == 'gem5':
run_args['userland_build_id'] = 'static'
if self.env['tests'] == []:
sources = [
'add.c',
'hello.c',
'hello_cpp.cpp',
'print_argv.c',
]
if self.env['arch'] == 'x86_64':
arch_sources = [
'asm_hello'
]
elif self.env['arch'] == 'aarch64':
arch_sources = [
'asm_hello'
]
else:
arch_sources = []
arch_sources[:] = [os.path.join('arch', self.env['arch'], arch_source) for arch_source in arch_sources]
sources.extend(arch_sources)
else:
sources = self.env['tests']
for source in sources:
run_args['userland'] = source
run_args['background'] = True
test_id_string = self.test_setup(run_args, source)
exit_status = run(**run_args)
self.test_teardown(run)
if exit_status != 0:
self.log_error('test failed, program exit status: {} test id: {}'.format(exit_status, test_id_string))
sys.exit(1)
if __name__ == '__main__':
Main().cli()

View File

@@ -11,50 +11,19 @@ class Main(common.LkmcCliFunction):
defaults={
'print_time': False,
},
)
self.add_argument(
'tests',
nargs='*',
help='''\
If given, run only the given tests. Otherwise, run all tests.
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()
if self.env['emulator'] == 'gem5':
run_args['userland_build_id'] = 'static'
if self.env['tests'] == []:
sources = [
'add.c',
'hello.c',
'hello_cpp.cpp',
'print_argv.c',
]
if self.env['arch'] == 'x86_64':
arch_sources = [
'asm_hello'
]
elif self.env['arch'] == 'aarch64':
arch_sources = [
'asm_hello'
]
else:
arch_sources = []
arch_sources[:] = [os.path.join('arch', self.env['arch'], arch_source) for arch_source in arch_sources]
sources.extend(arch_sources)
else:
sources = self.env['tests']
for source in sources:
run_args['userland'] = source
run_args['background'] = True
test_id_string = self.test_setup(run_args, source)
exit_status = run(**run_args)
self.test_teardown(run)
if exit_status != 0:
self.log_error('test failed, program exit status: {} test id: {}'.format(exit_status, test_id_string))
sys.exit(1)
run_args['eval_after'] = '/test_all.sh;/poweroff.out'
run(**run_args)
if __name__ == '__main__':
Main().cli()