test: also test all _public_ functions are listed in .sym files

Co-authored-by: Frantisek Sumsal <frantisek@sumsal.cz>
This commit is contained in:
Yu Watanabe 2023-04-29 13:56:40 +09:00
parent 9857de4f1c
commit 4c1b6e699f
4 changed files with 85 additions and 28 deletions

View file

@ -126,8 +126,10 @@ libsystemd_static = static_library(
userspace], userspace],
build_by_default : false) build_by_default : false)
libsystemd_dir_path = meson.current_source_dir()
libsystemd_sym = files('libsystemd.sym') libsystemd_sym = files('libsystemd.sym')
libsystemd_sym_path = meson.current_source_dir() / 'libsystemd.sym' libsystemd_sym_path = libsystemd_dir_path / 'libsystemd.sym'
static_libsystemd = get_option('static-libsystemd') static_libsystemd = get_option('static-libsystemd')
static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic' static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic'

View file

@ -15,11 +15,13 @@ libudev_sources = files(
libudev_includes = [includes, include_directories('.')] libudev_includes = [includes, include_directories('.')]
libudev_dir_path = meson.current_source_dir()
libudev_sym = files('libudev.sym') libudev_sym = files('libudev.sym')
libudev_sym_path = meson.current_source_dir() / 'libudev.sym' libudev_sym_path = libudev_dir_path / 'libudev.sym'
install_headers('libudev.h') install_headers('libudev.h')
libudev_h_path = meson.current_source_dir() / 'libudev.h' libudev_h_path = libudev_dir_path / 'libudev.h'
libudev_basic = static_library( libudev_basic = static_library(
'udev-basic', 'udev-basic',

View file

@ -1,36 +1,89 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
import sys, re import os
import re
import sys
print('#include <stdio.h>') def process_sym_file(file):
for header in sys.argv[2:]: for line in file:
m = re.search(r'^ +([a-zA-Z0-9_]+);', line)
if m:
if m[1] == 'sd_bus_object_vtable_format':
print(' {{"{0}", &{0}}},'.format(m[1]))
else:
print(' {{"{0}", {0}}},'.format(m[1]))
def process_source_file(file):
for line in file:
# Functions
m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*\(', line)
if m:
print(' {{ "{0}", {0} }},'.format(m[2]))
# Variables
m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*=', line)
if m:
print(' {{ "{0}", &{0} }},'.format(m[2]))
# Functions defined through a macro
m = re.search(r'^DEFINE_PUBLIC_TRIVIAL_REF_FUNC\([^,]+,\s*(\w+)\s*\)', line)
if m:
print(' {{ "{0}_ref", {0}_ref }},'.format(m[1]))
m = re.search(r'^DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC\([^,]+,\s*(\w+)\s*,', line)
if m:
print(' {{ "{0}_unref", {0}_unref }},'.format(m[1]))
m = re.search(r"^DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC\([^,]+,\s*(\w+)\s*,", line)
if m:
print(' {{ "{0}_ref", {0}_ref }},'.format(m[1]))
print(' {{ "{0}_unref", {0}_unref }},'.format(m[1]))
print('''/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdio.h>
#include <stdlib.h>
''')
for header in sys.argv[3:]:
print('#include "{}"'.format(header.split('/')[-1])) print('#include "{}"'.format(header.split('/')[-1]))
print(''' print('''
/* We want to check deprecated symbols too, without complaining */ /* We want to check deprecated symbols too, without complaining */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
''')
const struct { print('''
static const struct {
const char *name; const char *name;
const void *symbol; const void *symbol;
} symbols[] = {''') } symbols_from_sym[] = {''')
count = 0 with open(sys.argv[1], "r") as f:
for line in open(sys.argv[1]): process_sym_file(f)
match = re.search('^ +([a-zA-Z0-9_]+);', line)
if match:
s = match.group(1)
if s == 'sd_bus_object_vtable_format':
print(f' {{"{s}", &{s}}},')
else:
print(f' {{"{s}", {s}}},')
count += 1
print(f'''}}; print(''' {}
}, symbols_from_source[] = {''')
int main(void) {{ for dirpath, _, filenames in os.walk(sys.argv[2]):
for (size_t i = 0; i < {count}; i++) for filename in filenames:
printf("%p: %s\\n", symbols[i].symbol, symbols[i].name); with open(os.path.join(dirpath, filename), "r") as f:
return 0; process_source_file(f)
}}''')
print(''' {}
};
int main(void) {
size_t i, j;
puts("From symbol file:");
for (i = 0; symbols_from_sym[i].name; i++)
printf("%p: %s\\n", symbols_from_sym[i].symbol, symbols_from_sym[i].name);
puts("\\nFrom source files:");
for (j = 0; symbols_from_source[j].name; j++)
printf("%p: %s\\n", symbols_from_source[j].symbol, symbols_from_source[j].name);
puts("");
printf("Found %zu symbols from symbol file.\\n", i);
printf("Found %zu symbols from source files.\\n", j);
return i == j ? EXIT_SUCCESS : EXIT_FAILURE;
}''')

View file

@ -21,17 +21,17 @@ generate_sym_test_py = find_program('generate-sym-test.py')
test_libsystemd_sym_c = custom_target( test_libsystemd_sym_c = custom_target(
'test-libsystemd-sym.c', 'test-libsystemd-sym.c',
input : [libsystemd_sym_path] + systemd_headers, input : [libsystemd_sym_path] + systemd_headers + libsystemd_sources,
output : 'test-libsystemd-sym.c', output : 'test-libsystemd-sym.c',
command : [generate_sym_test_py, libsystemd_sym_path] + systemd_headers, command : [generate_sym_test_py, libsystemd_sym_path, libsystemd_dir_path] + systemd_headers,
capture : true, capture : true,
build_by_default : want_tests != 'false') build_by_default : want_tests != 'false')
test_libudev_sym_c = custom_target( test_libudev_sym_c = custom_target(
'test-libudev-sym.c', 'test-libudev-sym.c',
input : [libudev_sym_path, libudev_h_path], input : [libudev_sym_path, libudev_h_path] + libudev_sources,
output : 'test-libudev-sym.c', output : 'test-libudev-sym.c',
command : [generate_sym_test_py, '@INPUT0@', '@INPUT1@'], command : [generate_sym_test_py, libudev_sym_path, libudev_dir_path, libudev_h_path],
capture : true, capture : true,
build_by_default : want_tests != 'false') build_by_default : want_tests != 'false')