mirror of
https://github.com/systemd/systemd
synced 2024-10-02 22:37:25 +00:00
Merge pull request #27534 from keszybz/deperlify
Rewrite udev-test.pl in Python
This commit is contained in:
commit
c093bfe0ad
1
.github/workflows/build_test.sh
vendored
1
.github/workflows/build_test.sh
vendored
|
@ -48,7 +48,6 @@ PACKAGES=(
|
|||
mold
|
||||
mount
|
||||
net-tools
|
||||
perl
|
||||
python3-evdev
|
||||
python3-jinja2
|
||||
python3-lxml
|
||||
|
|
1
.github/workflows/unit_tests.sh
vendored
1
.github/workflows/unit_tests.sh
vendored
|
@ -19,7 +19,6 @@ ADDITIONAL_DEPS=(
|
|||
libtss2-dev
|
||||
libxkbcommon-dev
|
||||
libzstd-dev
|
||||
perl
|
||||
python3-libevdev
|
||||
python3-pefile
|
||||
python3-pyelftools
|
||||
|
|
|
@ -45,7 +45,6 @@ The following exceptions apply:
|
|||
* the following sources are licensed under the **CC0-1.0** license:
|
||||
- src/basic/siphash24.c
|
||||
- src/basic/siphash24.h
|
||||
- tools/check-includes.pl
|
||||
* the following sources are licensed under the **MIT-0** license:
|
||||
- all examples under man/
|
||||
- src/systemctl/systemd-sysv-install.SKELETON
|
||||
|
|
12
README
12
README
|
@ -195,7 +195,6 @@ REQUIREMENTS:
|
|||
libgcrypt (optional)
|
||||
libqrencode (optional)
|
||||
libmicrohttpd (optional)
|
||||
libpython (optional)
|
||||
libidn2 or libidn (optional)
|
||||
gnutls >= 3.1.4 (optional, >= 3.6.0 is required to support DNS-over-TLS with gnutls)
|
||||
openssl >= 1.1.0 (optional, required to support DNS-over-TLS with openssl)
|
||||
|
@ -206,17 +205,17 @@ REQUIREMENTS:
|
|||
gperf
|
||||
docbook-xsl (optional, required for documentation)
|
||||
xsltproc (optional, required for documentation)
|
||||
python >= 3.7 (required by meson too, >= 3.9 is required for ukify)
|
||||
python-jinja2
|
||||
python-pefile
|
||||
python-pefile (optional, required for ukify)
|
||||
python-lxml (optional, required to build the indices)
|
||||
python >= 3.5
|
||||
pyelftools (optional, required for systemd-boot)
|
||||
meson >= 0.53.2
|
||||
ninja
|
||||
gcc >= 4.7
|
||||
awk, sed, grep, and similar tools
|
||||
clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs
|
||||
from source code in C)
|
||||
pyelftools (optional, required for systemd-boot)
|
||||
|
||||
During runtime, you need the following additional
|
||||
dependencies:
|
||||
|
@ -270,8 +269,9 @@ REQUIREMENTS:
|
|||
Additional packages are necessary to run some tests:
|
||||
- busybox (used by test/TEST-13-NSPAWN-SMOKE)
|
||||
- nc (used by test/TEST-12-ISSUE-3171)
|
||||
- python3-pyparsing
|
||||
- python3-evdev (used by hwdb parsing tests)
|
||||
- python (test-udev which is installed is in python)
|
||||
- python-pyparsing
|
||||
- python-evdev (used by hwdb parsing tests)
|
||||
- strace (used by test/test-functions)
|
||||
- capsh (optional, used by test-execute)
|
||||
|
||||
|
|
45
meson.build
45
meson.build
|
@ -701,7 +701,6 @@ stat = find_program('stat')
|
|||
ln = find_program('ln')
|
||||
git = find_program('git', required : false)
|
||||
env = find_program('env')
|
||||
perl = find_program('perl', required : false)
|
||||
rsync = find_program('rsync', required : false)
|
||||
diff = find_program('diff')
|
||||
find = find_program('find')
|
||||
|
@ -2132,7 +2131,7 @@ endif
|
|||
conf.set10('ENABLE_UKIFY', want_ukify)
|
||||
|
||||
############################################################
|
||||
#
|
||||
|
||||
elf2efi_lds = project_source_root / 'tools/elf2efi.lds'
|
||||
elf2efi_py = find_program('tools/elf2efi.py')
|
||||
export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
|
||||
|
@ -4416,6 +4415,7 @@ foreach test : simple_tests
|
|||
tests += { 'sources' : [test] }
|
||||
endforeach
|
||||
|
||||
TESTS = {}
|
||||
foreach test : tests
|
||||
sources = test.get('sources')
|
||||
condition = test.get('condition', '')
|
||||
|
@ -4462,11 +4462,13 @@ foreach test : tests
|
|||
message('@0@ is an unsafe test'.format(name))
|
||||
elif want_tests != 'false'
|
||||
test(name, exe,
|
||||
env : test_env,
|
||||
timeout : test.get('timeout', 30),
|
||||
suite : suite,
|
||||
is_parallel : test.get('parallel', true))
|
||||
env : test_env,
|
||||
timeout : test.get('timeout', 30),
|
||||
suite : suite,
|
||||
is_parallel : test.get('parallel', true))
|
||||
endif
|
||||
|
||||
TESTS += { name : exe }
|
||||
endforeach
|
||||
|
||||
exe = executable(
|
||||
|
@ -4528,6 +4530,16 @@ if want_tests != 'false' and static_libudev_pic
|
|||
test('test-libudev-static-sym', exe)
|
||||
endif
|
||||
|
||||
if want_tests != 'false'
|
||||
udev_rule_runner = TESTS['udev-rule-runner'].full_path()
|
||||
|
||||
test('test-udev',
|
||||
test_udev_py,
|
||||
args : ['-v'],
|
||||
env : ['UDEV_RULE_RUNNER=@0@'.format(udev_rule_runner)],
|
||||
timeout : 180)
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
||||
foreach fuzzer : simple_fuzzers
|
||||
|
@ -4726,7 +4738,7 @@ if git.found()
|
|||
all_files = run_command(
|
||||
env, '-u', 'GIT_WORK_TREE',
|
||||
git, '--git-dir=@0@/.git'.format(project_source_root),
|
||||
'ls-files', ':/*.[ch]',
|
||||
'ls-files', ':/*.[ch]', ':/*.cc',
|
||||
check : false)
|
||||
if all_files.returncode() == 0
|
||||
all_files = files(all_files.stdout().split())
|
||||
|
@ -4738,17 +4750,26 @@ if git.found()
|
|||
run_target(
|
||||
'ctags',
|
||||
command : [env, 'ctags', '--tag-relative=never', '-o', '@0@/tags'.format(project_source_root)] + all_files)
|
||||
endif
|
||||
endif
|
||||
|
||||
if git.found()
|
||||
############################################
|
||||
|
||||
if want_tests != 'false' and conf.get('BUILD_MODE_DEVELOPER') == 1
|
||||
test('check-includes',
|
||||
files('tools/check-includes.py'),
|
||||
args: all_files,
|
||||
env : ['PROJECT_SOURCE_ROOT=@0@'.format(project_source_root)])
|
||||
endif
|
||||
endif
|
||||
|
||||
####################################################
|
||||
|
||||
git_contrib_sh = find_program('tools/git-contrib.sh')
|
||||
run_target(
|
||||
'git-contrib',
|
||||
command : [git_contrib_sh])
|
||||
endif
|
||||
|
||||
if git.found()
|
||||
####################################################
|
||||
|
||||
git_head = run_command(
|
||||
git, '--git-dir=@0@/.git'.format(project_source_root),
|
||||
'rev-parse', 'HEAD',
|
||||
|
|
|
@ -23,7 +23,6 @@ BuildPackages=
|
|||
glib2
|
||||
libxslt
|
||||
linux-api-headers
|
||||
perl
|
||||
python
|
||||
python-jinja
|
||||
python-lxml
|
||||
|
|
|
@ -29,7 +29,6 @@ BuildPackages=
|
|||
findutils
|
||||
libxslt
|
||||
pam-devel
|
||||
perl-interpreter
|
||||
pkgconfig(audit)
|
||||
pkgconfig(blkid)
|
||||
pkgconfig(bzip2)
|
||||
|
|
|
@ -99,8 +99,6 @@ enum JobResult {
|
|||
_JOB_RESULT_INVALID = -EINVAL,
|
||||
};
|
||||
|
||||
#include "unit.h"
|
||||
|
||||
struct JobDependency {
|
||||
/* Encodes that the 'subject' job needs the 'object' job in
|
||||
* some way. This structure is used only while building a transaction. */
|
||||
|
|
|
@ -409,7 +409,7 @@ tests += [
|
|||
'timeout' : 120,
|
||||
},
|
||||
{
|
||||
'sources' : files('test-udev.c'),
|
||||
'sources' : files('udev-rule-runner.c'),
|
||||
'link_with' : [
|
||||
libshared,
|
||||
libudevd_core,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "mkdir-label.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
|
@ -61,11 +62,11 @@ static int fake_filesystems(void) {
|
|||
const char *error;
|
||||
bool ignore_mount_error;
|
||||
} fakefss[] = {
|
||||
{ "test/tmpfs/sys", "/sys", "Failed to mount test /sys", false },
|
||||
{ "test/tmpfs/dev", "/dev", "Failed to mount test /dev", false },
|
||||
{ "test/run", "/run", "Failed to mount test /run", false },
|
||||
{ "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true },
|
||||
{ "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
|
||||
{ "tmpfs/sys", "/sys", "Failed to mount test /sys", false },
|
||||
{ "tmpfs/dev", "/dev", "Failed to mount test /dev", false },
|
||||
{ "run", "/run", "Failed to mount test /run", false },
|
||||
{ "run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true },
|
||||
{ "run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
|
||||
};
|
||||
int r;
|
||||
|
||||
|
@ -92,9 +93,9 @@ static int run(int argc, char *argv[]) {
|
|||
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
if (!IN_SET(argc, 2, 3))
|
||||
if (!IN_SET(argc, 2, 3, 4))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"This program needs one or two arguments, %d given", argc - 1);
|
||||
"This program needs between one and three arguments, %d given", argc - 1);
|
||||
|
||||
r = fake_filesystems();
|
||||
if (r < 0)
|
||||
|
@ -123,10 +124,18 @@ static int run(int argc, char *argv[]) {
|
|||
action = argv[1];
|
||||
devpath = argv[2];
|
||||
|
||||
if (argv[3]) {
|
||||
unsigned us;
|
||||
|
||||
r = safe_atou(argv[3], &us);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Invalid delay '%s': %m", argv[3]);
|
||||
usleep(us);
|
||||
}
|
||||
|
||||
assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0);
|
||||
|
||||
const char *syspath;
|
||||
syspath = strjoina("/sys", devpath);
|
||||
const char *syspath = strjoina("/sys", devpath);
|
||||
r = device_new_from_synthetic_event(&dev, syspath, action);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to open device '%s'", devpath);
|
|
@ -18,13 +18,15 @@ import textwrap
|
|||
|
||||
try:
|
||||
import pytest
|
||||
except ImportError:
|
||||
except ImportError as e:
|
||||
print(str(e), file=sys.stderr)
|
||||
sys.exit(77)
|
||||
|
||||
try:
|
||||
# pyflakes: noqa
|
||||
import pefile # noqa
|
||||
except ImportError:
|
||||
except ImportError as e:
|
||||
print(str(e), file=sys.stderr)
|
||||
sys.exit(77)
|
||||
|
||||
# We import ukify.py, which is a template file. But only __version__ is
|
||||
|
|
|
@ -123,23 +123,14 @@ endif
|
|||
|
||||
############################################################
|
||||
|
||||
# prepare test/sys tree
|
||||
sys_script_py = find_program('sys-script.py')
|
||||
custom_target(
|
||||
'sys',
|
||||
command : [sys_script_py, meson.current_build_dir()],
|
||||
output : 'sys',
|
||||
build_by_default : want_tests != 'false')
|
||||
sys_script_py = files('sys-script.py')
|
||||
test_udev_py = files('test-udev.py')
|
||||
|
||||
if perl.found()
|
||||
udev_test_pl = find_program('udev-test.pl')
|
||||
if want_tests != 'false'
|
||||
test('udev-test',
|
||||
udev_test_pl,
|
||||
timeout : 180)
|
||||
endif
|
||||
else
|
||||
message('Skipping udev-test because perl is not available')
|
||||
if install_tests
|
||||
install_data(
|
||||
sys_script_py,
|
||||
test_udev_py,
|
||||
install_dir : unittestsdir)
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
|
|
@ -52,6 +52,9 @@ for test in tests:
|
|||
elif ex.returncode == 77:
|
||||
print(f'{YELLOW}SKIP: {name}{RESET_ALL}')
|
||||
total.skip += 1
|
||||
elif ex.returncode == 127:
|
||||
print(f'{YELLOW}SKIP: {name} (no interpeter) {RESET_ALL}')
|
||||
total.skip += 1
|
||||
else:
|
||||
print(f'{RED}FAIL: {name}{RESET_ALL}')
|
||||
total.fail += 1
|
||||
|
|
|
@ -4,4 +4,4 @@ Description=https://github.com/systemd/systemd/issues/2637
|
|||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh -x -c "! test -x perl || perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'"
|
||||
ExecStart=/bin/bash -x -c "[[ %%U == ?U ]]"
|
||||
|
|
|
@ -818,19 +818,19 @@ install_valgrind() {
|
|||
exit 1
|
||||
fi
|
||||
|
||||
local valgrind_bins valgrind_libs valgrind_dbg_and_supp
|
||||
local valgrind_bins valgrind_libs valgrind_supp
|
||||
|
||||
readarray -t valgrind_bins < <(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/')
|
||||
readarray -t valgrind_bins < <(strace -e execve valgrind /bin/true 2>&1 >/dev/null |
|
||||
sed -r -n 's/execve\("([^"]*)".*/\1/p')
|
||||
image_install "${valgrind_bins[@]}"
|
||||
|
||||
readarray -t valgrind_libs < <(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')
|
||||
readarray -t valgrind_libs < <(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null |
|
||||
sed -r -n 's|.*calling init: (/.*vgpreload_.*)|\1|p')
|
||||
image_install "${valgrind_libs[@]}"
|
||||
|
||||
readarray -t valgrind_dbg_and_supp < <(
|
||||
strace -e open valgrind /bin/true 2>&1 >/dev/null |
|
||||
perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }'
|
||||
)
|
||||
image_install "${valgrind_dbg_and_supp[@]}"
|
||||
readarray -t valgrind_supp < <(strace -e open valgrind /bin/true 2>&1 >/dev/null |
|
||||
sed -r -n 's,open\("([^"]*(/debug[^"]*|\.supp))".*= [0-9].*,\1,p')
|
||||
image_install "${valgrind_supp[@]}"
|
||||
}
|
||||
|
||||
create_valgrind_wrapper() {
|
||||
|
@ -1455,16 +1455,13 @@ check_asan_reports() {
|
|||
ret=$((ret+1))
|
||||
fi
|
||||
|
||||
# May 08 13:23:31 H testleak[2907148]: SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
|
||||
pids="$(
|
||||
"$JOURNALCTL" -D "$root/var/log/journal" | perl -alne '
|
||||
BEGIN {
|
||||
%services_to_ignore = (
|
||||
"dbus-daemon" => undef,
|
||||
"dbus-broker-launch" => undef,
|
||||
);
|
||||
}
|
||||
print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}'
|
||||
"$JOURNALCTL" -D "$root/var/log/journal" --grep 'SUMMARY: .*Sanitizer:' |
|
||||
grep -v -E 'dbus-daemon|dbus-broker-launch' |
|
||||
sed -r -n 's/.* .+\[([0-9]+)\]: SUMMARY:.*/\1/p'
|
||||
)"
|
||||
|
||||
if [[ -n "$pids" ]]; then
|
||||
ret=$((ret+1))
|
||||
for pid in $pids; do
|
||||
|
|
2434
test/test-udev.py
Executable file
2434
test/test-udev.py
Executable file
File diff suppressed because it is too large
Load diff
2911
test/udev-test.pl
2911
test/udev-test.pl
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@ function report_result() {
|
|||
local name="${1##*/}"
|
||||
local ret=$2
|
||||
|
||||
if [[ $ret -ne 0 && $ret != 77 ]]; then
|
||||
if [[ $ret -ne 0 && $ret != 77 && $ret != 127 ]]; then
|
||||
echo "$name failed with $ret"
|
||||
echo "$name" >>/failed-tests
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ function report_result() {
|
|||
cat "/$name.log"
|
||||
echo "--- $name end ---"
|
||||
} >>/failed
|
||||
elif [[ $ret == 77 ]]; then
|
||||
elif [[ $ret == 77 || $ret == 127 ]]; then
|
||||
echo "$name skipped"
|
||||
echo "$name" >>/skipped-tests
|
||||
{
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# SPDX-License-Identifier: CC0-1.0
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# checkincludes: Find files included more than once in (other) files.
|
||||
|
||||
foreach $file (@ARGV) {
|
||||
open(FILE, $file) or die "Cannot open $file: $!.\n";
|
||||
|
||||
my %includedfiles = ();
|
||||
|
||||
while (<FILE>) {
|
||||
if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
|
||||
++$includedfiles{$1};
|
||||
}
|
||||
}
|
||||
foreach $filename (keys %includedfiles) {
|
||||
if ($includedfiles{$filename} > 1) {
|
||||
print "$file: $filename is included more than once.\n";
|
||||
}
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
}
|
32
tools/check-includes.py
Executable file
32
tools/check-includes.py
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
# pylint: disable=missing-docstring,invalid-name,unspecified-encoding,consider-using-with
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
PROJECT_ROOT = pathlib.Path(os.getenv('PROJECT_SOURCE_ROOT', '.'))
|
||||
|
||||
def check_file(filename):
|
||||
seen = set()
|
||||
good = True
|
||||
for n, line in enumerate(open(filename)):
|
||||
m = re.match(r'^\s*#\s*include\s*[<"](\S*)[>"]', line)
|
||||
if m:
|
||||
include = m.group(1)
|
||||
if include in seen:
|
||||
try:
|
||||
filename = pathlib.Path(filename).resolve().relative_to(PROJECT_ROOT)
|
||||
except ValueError:
|
||||
pass
|
||||
print(f'{filename}:{n}: {line.strip()}')
|
||||
good = False
|
||||
seen.add(include)
|
||||
return good
|
||||
|
||||
if __name__ == '__main__':
|
||||
good = all(check_file(name) for name in sys.argv[1:])
|
||||
sys.exit(0 if good else 1)
|
|
@ -109,12 +109,12 @@ install -Dt "$OUT/src/shared/" \
|
|||
# Most i386 libraries have to be brought to the runtime environment somehow. Ideally they
|
||||
# should be linked statically but since it isn't possible another way to keep them close
|
||||
# to the fuzz targets is used here. The dependencies are copied to "$OUT/src/shared" and
|
||||
# then `rpath` is tweaked to make it possible for the linker to find them there. "$OUT/src/shared"
|
||||
# then 'rpath' is tweaked to make it possible for the linker to find them there. "$OUT/src/shared"
|
||||
# is chosen because the runtime search path of all the fuzz targets already points to it
|
||||
# to load "libsystemd-shared" and "libsystemd-core". Stuff like that should be avoided on
|
||||
# x86_64 because it tends to break coverage reports, fuzz-introspector, CIFuzz and so on.
|
||||
if [[ "$ARCHITECTURE" == i386 ]]; then
|
||||
for lib_path in $(ldd "$OUT"/src/shared/libsystemd-shared-*.so | perl -lne 'print $1 if m{=>\s+(/lib\S+)}'); do
|
||||
for lib_path in $(ldd "$OUT"/src/shared/libsystemd-shared-*.so | awk '/=> \/lib/ { print $3 }'); do
|
||||
lib_name=$(basename "$lib_path")
|
||||
cp "$lib_path" "$OUT/src/shared"
|
||||
patchelf --set-rpath \$ORIGIN "$OUT/src/shared/$lib_name"
|
||||
|
|
Loading…
Reference in a new issue