Files
libfprint/tests/meson.build
T
Ge-org Brohammer 3a41fa7ccc tests/realtek: Cover the storage error path that returned a freed GError
Deleting a print whose template is not in the sensor's storage makes the
driver fail its task SSM, which is the path that handed an already-freed
GError to fpi_device_delete_complete(). Reading the reported error is
therefore what the test is for.

No enrollment is involved: the test deserializes a stored realtek print
whose template is deliberately not on the device, so the recording needs
no finger presses and the capture stays at 90 packets.

Without the previous commit the test dies rather than fails:

  umockdev-run ... died with <Signals.SIGSEGV: 11>
  1/1 drivers+custom - libfprint:realtek-storage-errors FAIL

The duplicate-enrollment path reaches the same bug through
fp_enroll_ssm_done(), but capturing it needs two full enrollments and
some 1.07M packets of polling traffic, so it is left out here.
2026-08-28 15:19:30 +02:00

472 lines
15 KiB
Meson

envs = environment()
# Enable debug messages and abort on warnings
envs.set('G_DEBUG', 'fatal-warnings')
envs.set('G_MESSAGES_DEBUG', 'all')
# Setup paths
envs.set('MESON_SOURCE_ROOT', meson.project_source_root())
envs.set('MESON_BUILD_ROOT', meson.project_build_root())
envs.set('G_TEST_SRCDIR', meson.current_source_dir())
envs.set('G_TEST_BUILDDIR', meson.current_build_dir())
envs.prepend('LD_LIBRARY_PATH', meson.project_build_root() / 'libfprint')
# Set fp_device_emulation_env_var so that drivers can adapt (e.g. to use fixed
# random numbers rather than proper ones)
fp_device_emulation_env_var = 'FP_DEVICE_EMULATION'
envs.set(fp_device_emulation_env_var, '1')
# Set a colon-separated list of native drivers we enable in tests
envs.set('FP_DRIVERS_ALLOWLIST', ':'.join([
'virtual_image',
'virtual_device',
'virtual_device_storage',
]))
envs.set('FP_PRINTS_PATH', meson.project_source_root() / 'examples' / 'prints')
envs.set('NO_AT_BRIDGE', '1')
installed_tests = get_option('installed-tests')
installed_tests_execdir = libexecdir / 'installed-tests' / versioned_libname
installed_tests_testdir = datadir / 'installed-tests' / versioned_libname
installed_tests_libdir = libdir
drivers_tests = {
'aes2501': { 'timeout': 20 },
'aes2550': {},
'aes3500': {},
'elan': {},
'elan-cobo': {},
'elanmoc': {},
'elanspi': { 'timeout': 30 },
'synaptics': {},
'upektc_img': {},
'upektc_img-tcs1s': {},
'uru4000-msv2': {},
'uru4000-4500': {},
'vfs0050': {},
'vfs301': {},
'vfs5011': {},
'vfs7552': {},
'goodixmoc': {},
'nb1010': {},
'egis0570': {},
'egismoc': {},
'egis_etu905': {},
'egismoc-05a1': {},
'egismoc-0586': {},
'egismoc-0587': {},
'fpcmoc': {},
'realtek': {},
'realtek-5816': {},
'realtek-storage-errors': {},
'focaltech_moc': { 'timeout': 30 },
'focaltech_moc-6553': {},
'mafpmoc': {},
'secugen': {},
}
if get_option('introspection')
conf = configuration_data()
conf.set('SRCDIR', meson.project_source_root())
conf.set('BUILDDIR', meson.project_build_root())
configure_file(configuration: conf,
input: 'create-driver-test.py.in',
output: 'create-driver-test.py')
endif
test_emulation_lib = shared_library('fprint-test-emulation',
'test-emulation.c',
dependencies: libfprint_private_dep,
install: installed_tests,
install_dir: installed_tests_execdir,
)
# Paths where the test-emulation helper may be loaded via dlopen
test_emulation = configuration_data()
test_emulation.set_quoted('FPI_EMULATION_ENV_VAR',
fp_device_emulation_env_var)
test_emulation.set_quoted('FPI_EMULATION_HELPER_BUILDDIR',
meson.project_build_root() / 'tests')
test_emulation.set_quoted('FPI_EMULATION_HELPER_INSTALLDIR',
libexecdir / 'installed-tests' / versioned_libname)
test_emulation.set_quoted('FPI_EMULATION_HELPER_MODULE',
fs.name(test_emulation_lib.full_path()))
configure_file(output: 'fpi-test-emulation.h', configuration: test_emulation)
env_parser_cmd = '''
import os;
print(" ".join([f"{k}={v}" for k, v in os.environ.items()
if k.startswith("FP_") or k.startswith("G_")]))
'''
envs_str = run_command(python3, '-c', env_parser_cmd,
env: envs,
check: installed_tests).stdout().strip()
envs_str = ' '.join([
envs_str,
'G_TEST_SRCDIR=' + installed_tests_testdir,
'G_TEST_BUILDDIR=' + installed_tests_execdir,
])
if get_option('introspection')
envs.prepend('GI_TYPELIB_PATH', meson.project_build_root() / 'libfprint')
virtual_devices_tests = [
'virtual-image',
'virtual-device',
]
unittest_inspector = find_program('unittest_inspector.py')
umockdev_test_name = 'umockdev-test.py'
umockdev_test = find_program(umockdev_test_name)
foreach vdtest: virtual_devices_tests
driver_name = '_'.join(vdtest.split('-'))
if driver_name in drivers
base_args = files(vdtest + '.py')
suite = ['virtual-driver']
r = run_command(unittest_inspector, files(vdtest + '.py'), check: false)
unit_tests = r.stdout().strip().split('\n')
if r.returncode() == 0 and unit_tests.length() > 0
suite += vdtest
elif r.returncode() == 77
test(vdtest,
sh,
args: ['-c', 'exit 77']
)
continue
else
unit_tests = [vdtest]
endif
foreach ut: unit_tests
ut_suite = suite
ut_args = base_args
if unit_tests.length() > 1
ut_args += ut
ut_suite += ut.split('.')[0]
endif
test(ut,
python3,
args: ut_args,
suite: ut_suite,
depends: [
libfprint_typelib,
test_emulation_lib,
],
env: envs,
)
endforeach
if installed_tests
install_data(base_args,
install_dir: installed_tests_execdir,
install_mode: 'rwxr-xr-x',
)
configure_file(
input: 'test.in',
output: vdtest + '.test',
install_dir: installed_tests_testdir,
configuration: {
'exec': installed_tests_execdir / fs.name(base_args[0]),
'env': ' '.join([
envs_str,
'LD_LIBRARY_PATH=' + installed_tests_libdir,
'FP_PRINTS_PATH=' + installed_tests_testdir / 'prints',
# FIXME: Adding this requires gnome-desktop-testing!12
# 'GI_TYPELIB_PATH=' + installed_tests_libdir / 'girepository-1.0',
]),
'extra_content': '',
},
)
endif
else
test(vdtest,
sh,
args: ['-c', 'exit 77']
)
endif
endforeach
driver_tests_enabled = false
foreach driver_test, args: drivers_tests
driver_name = driver_test.split('-')[0]
driver_envs = envs
driver_envs.set('FP_DRIVERS_ALLOWLIST', driver_name)
if (driver_name in supported_drivers and
gusb_dep.version().version_compare('>= 0.3.0'))
test_types = []
foreach test_type: args.get('test_types', ['custom', 'capture'])
test_file_prefix = meson.current_source_dir() / driver_test / test_type
if fs.exists(test_file_prefix + '.py')
test_types += [test_type]
elif fs.exists(test_file_prefix + '.png')
test_types += [test_type]
elif fs.exists(test_file_prefix + '.ioctl')
test_types += [test_type]
elif fs.exists(test_file_prefix + '.pcapng')
test_types += [test_type]
endif
endforeach
assert(test_types.length() > 0,
'No test types found for driver ' + driver_test)
foreach test_type: test_types
driver_tests_enabled = true
test_name = driver_test + (test_types.length() > 1 ? '-' + test_type : '')
test(test_name,
python3,
args: [
umockdev_test.full_path(),
meson.current_source_dir() / driver_test,
'--test', test_type,
],
env: driver_envs,
is_parallel: args.get('is_parallel', true),
priority: args.get('priority', 0),
protocol: args.get('protocol', 'exitcode'),
should_fail: args.get('should_fail', false),
suite: ['drivers', test_type] + args.get('suite', []),
timeout: args.get('timeout', 15),
verbose: args.get('verbose', false),
depends: [
libfprint_typelib,
test_emulation_lib,
],
)
endforeach
if installed_tests
driver_envs_str = run_command(python3, '-c', env_parser_cmd,
env: driver_envs,
check: true).stdout().strip()
configure_file(
input: 'driver.test.in',
output: 'driver-' + driver_test + '.test',
install_dir: installed_tests_testdir,
configuration: {
'installed_tests_execdir': installed_tests_execdir,
'installed_tests_testdir': installed_tests_testdir,
'umockdev_test_name': umockdev_test_name,
'driver_test': driver_test,
'driver_env': ' '.join([
driver_envs_str,
'LD_LIBRARY_PATH=' + installed_tests_libdir,
# FIXME: Adding this requires gnome-desktop-testing!12
# 'GI_TYPELIB_PATH=' + installed_tests_libdir / 'girepository-1.0',
]),
},
)
install_subdir(driver_test, install_dir: installed_tests_testdir)
endif
else
test(driver_test,
sh,
args: ['-c', 'exit 77']
)
endif
endforeach
if installed_tests and driver_tests_enabled
install_data(umockdev_test.full_path(),
install_dir: installed_tests_execdir,
install_mode: 'rwxr-xr-x',
)
install_data('capture.py',
install_dir: installed_tests_execdir,
install_mode: 'rwxr-xr-x',
)
endif
else
warning('Skipping all driver tests as introspection bindings are missing')
test('virtual-image',
sh,
args: ['-c', 'exit 77']
)
foreach driver_test: drivers_tests
test(driver_test,
sh,
args: ['-c', 'exit 77']
)
endforeach
endif
test_utils = static_library('fprint-test-utils',
sources: [
'test-utils.c',
'test-device-fake.c',
],
dependencies: libfprint_private_dep,
install: false)
unit_tests = [
'fpi-device',
'fpi-ssm',
'fpi-assembling',
]
if 'virtual_image' in drivers
unit_tests += [
'fp-context',
'fp-device',
]
endif
unit_tests_deps = { 'fpi-assembling' : [cairo_dep] }
foreach test_name: unit_tests
if unit_tests_deps.has_key(test_name)
missing_deps = false
foreach dep: unit_tests_deps[test_name]
if not dep.found()
missing_deps = true
break
endif
endforeach
if missing_deps
# Create a dummy test that always skips instead
warning('Test @0@ cannot be compiled due to missing dependencies'.format(test_name))
test(test_name,
sh,
suite: ['unit-tests'],
args: ['-c', 'exit 77'],
)
continue
endif
extra_deps = unit_tests_deps[test_name]
else
extra_deps = []
endif
basename = 'test-' + test_name
test_exe = executable(basename,
sources: basename + '.c',
dependencies: [ libfprint_private_dep ] + extra_deps,
c_args: common_cflags,
link_whole: test_utils,
install: installed_tests,
install_dir: installed_tests_execdir,
)
test(test_name,
test_exe,
suite: ['unit-tests'],
env: envs,
)
configure_file(
input: 'test.in',
output: test_name + '.test',
install: installed_tests,
install_dir: installed_tests_testdir,
configuration: {
'exec': installed_tests_execdir / basename,
'env': envs_str,
'extra_content': 'TestEnvironment=LD_LIBRARY_PATH=' +
installed_tests_libdir,
},
)
endforeach
# Run udev rule generator with fatal warnings
hwdb_envs = envs
hwdb_envs.set('UDEV_HWDB', udev_hwdb.full_path())
hwdb_envs.set('UDEV_HWDB_CHECK_CONTENTS', default_drivers_are_enabled ? '1' : '0')
hwdb_envs.set('G_MESSAGES_DEBUG', '')
test('udev-hwdb',
find_program('test-generated-hwdb.sh'),
depends: udev_hwdb,
suite: ['data', 'no-valgrind'],
env: hwdb_envs,
)
appstreamcli = find_program('appstreamcli', required: false)
if appstreamcli.found()
test('metainfo-validate',
appstreamcli,
args: ['validate', metainfo_generator],
depends: metainfo_generator,
suite: ['data', 'no-valgrind'],
)
endif
gdb = find_program('gdb', required: false)
if gdb.found() and libfprint_sanitizers.length() == 0
libfprint_wrapper = [
gdb.full_path(),
'-batch',
'-ex', 'run',
'--args',
]
add_test_setup('gdb',
timeout_multiplier: 1000,
exe_wrapper: libfprint_wrapper,
env: [
'LIBFPRINT_TEST_WRAPPER=' + ' '.join(libfprint_wrapper),
])
endif
if ('address' in libfprint_sanitizers or
'undefined' in libfprint_sanitizers or
'leak' in libfprint_sanitizers)
add_test_setup('sanitizers',
is_default: true,
timeout_multiplier: 3,
env: [
'ASAN_OPTIONS=verify_asan_link_order=0',
])
endif
valgrind = find_program('valgrind', required: false)
if valgrind.found() and libfprint_sanitizers.length() == 0
glib_share = glib_dep.get_variable(pkgconfig: 'prefix') / 'share' / glib_dep.name()
glib_suppressions = glib_share + '/valgrind/glib.supp'
libfprint_suppressions = files('libfprint.supp')[0]
python_suppressions = files('valgrind-python.supp')[0]
if meson.version().version_compare('>=1.4')
libfprint_suppressions = libfprint_suppressions.full_path()
python_suppressions = python_suppressions.full_path()
else
libfprint_suppressions = meson.project_source_root() / '@0@'.format(libfprint_suppressions)
python_suppressions = meson.project_source_root() / '@0@'.format(python_suppressions)
endif
libfprint_wrapper = [
valgrind.full_path(),
'--tool=memcheck',
'--leak-check=full',
'--leak-resolution=high',
'--error-exitcode=1',
'--errors-for-leak-kinds=definite',
'--track-origins=yes',
'--show-leak-kinds=definite,possible',
'--show-error-list=yes',
'--gen-suppressions=all',
'--suppressions=' + libfprint_suppressions,
'--suppressions=' + glib_suppressions,
'--suppressions=' + python_suppressions,
]
add_test_setup('valgrind',
timeout_multiplier: 20,
exe_wrapper: libfprint_wrapper,
exclude_suites: ['no-valgrind'],
env: [
'G_SLICE=always-malloc',
'UNDER_VALGRIND=1',
'FP_VIRTUAL_IMAGE_HOT_SECONDS=-1',
'FP_VIRTUAL_DEVICE_HOT_SECONDS=-1',
'LIBFPRINT_TEST_WRAPPER=' + ' '.join(libfprint_wrapper),
])
endif