From dc67223a683fb2b020bffcc8b870fa8dc98a6c97 Mon Sep 17 00:00:00 2001 From: Samaresh Kumar Singh Date: Thu, 11 Jun 2026 14:53:32 -0500 Subject: [PATCH] Fix api_base_test failures with shared only builds and on modern glibc The test mocks libc functions with the linker wrap option, which only works when the DAQ library is linked statically into the test binary. Link against a check only convenience library so make check passes when configured with --disable-static. Also pick the stat wrapper based on the glibc version since glibc 2.33 removed the extern inline that redirected stat to __xstat. Fix for the issue #23 and #30. --- api/Makefile.am | 10 ++++++++++ test/Makefile.am | 6 ++++-- test/api_base_test.c | 12 ++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/api/Makefile.am b/api/Makefile.am index 833ffb1..79408e1 100644 --- a/api/Makefile.am +++ b/api/Makefile.am @@ -8,3 +8,13 @@ libdaq_la_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) libdaq_la_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) libdaq_la_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) -version-info 3:0:0 libdaq_la_LIBADD = $(LIBDL) + +# Convenience library for the unit tests. The tests mock libc functions with +# ld's --wrap option, which only affects symbols resolved at static link time, +# so they must link the DAQ library statically even when configured with +# --disable-static. +check_LTLIBRARIES = libdaq_check.la +libdaq_check_la_SOURCES = $(libdaq_la_SOURCES) +libdaq_check_la_CPPFLAGS = $(libdaq_la_CPPFLAGS) +libdaq_check_la_CFLAGS = $(libdaq_la_CFLAGS) +libdaq_check_la_LIBADD = $(LIBDL) diff --git a/test/Makefile.am b/test/Makefile.am index acfa805..160ec86 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,7 +6,6 @@ api_base_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) $(CMOCKA_CFLAGS) -I$ api_base_test_LDFLAGS = \ $(AM_LDFLAGS) \ $(CODE_COVERAGE_LDFLAGS) \ - -static-libtool-libs \ -Wl,--wrap,printf \ -Wl,--wrap,__printf_chk \ -Wl,--wrap,fprintf \ @@ -19,7 +18,7 @@ api_base_test_LDFLAGS = \ -Wl,--wrap,dlopen \ -Wl,--wrap,dlsym \ -Wl,--wrap,dlclose -api_base_test_LDADD = ${top_builddir}/api/libdaq.la $(LIBDL) $(CMOCKA_LIBS) +api_base_test_LDADD = ${top_builddir}/api/libdaq_check.la $(LIBDL) $(CMOCKA_LIBS) api_config_test_SOURCES = api_config_test.c daq_test_module.c daq_test_module.h api_config_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) $(CMOCKA_CFLAGS) -I${top_srcdir}/api @@ -28,3 +27,6 @@ api_config_test_LDFLAGS = \ $(CODE_COVERAGE_LDFLAGS) \ -static-libtool-libs api_config_test_LDADD = ${top_builddir}/api/libdaq.la $(LIBDL) $(CMOCKA_LIBS) + +${top_builddir}/api/libdaq_check.la: + $(MAKE) -C ${top_builddir}/api libdaq_check.la diff --git a/test/api_base_test.c b/test/api_base_test.c index 4532c38..18d043c 100644 --- a/test/api_base_test.c +++ b/test/api_base_test.c @@ -135,7 +135,15 @@ int __wrap_closedir(DIR *dirp) return 0; } +/* Prior to glibc 2.33, stat() could be an extern inline function calling __xstat(), + so references from the library under test resolve to __xstat instead of stat. */ #ifdef __USE_EXTERN_INLINES +#if !defined(__GLIBC_PREREQ) || !__GLIBC_PREREQ(2, 33) +#define WRAP_XSTAT +#endif +#endif + +#ifdef WRAP_XSTAT int __wrap___xstat(int ver, const char *pathname, struct stat *buf); int __wrap___xstat(int ver, const char *pathname, struct stat *buf) @@ -155,7 +163,7 @@ int __wrap_stat(const char *pathname, struct stat *buf) return mock(); } -#endif /* __USE_EXTERN_INLINES */ +#endif /* WRAP_XSTAT */ void *__wrap_dlopen(const char *filename, int flags); void *__wrap_dlopen(const char *filename, int flags) @@ -286,7 +294,7 @@ static void test_daq_load_modules(void **state) expect_value(__wrap_readdir, dirp, 0xdeadbeef); will_return(__wrap_readdir, &deadbeef_dir_entry); -#ifdef __USE_EXTERN_INLINES +#ifdef WRAP_XSTAT expect_string(__wrap___xstat, pathname, MODULE_PATH "/" BAD_MODULE_NAME ".so"); will_return(__wrap___xstat, 0); #else