From 2990db8d1a4f8afab3087de00de4ddad6baec91c Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 28 Nov 2014 22:26:57 +0000 Subject: [PATCH] tests/c-api: Test that the library can really be loaded with dlopen. Answer is yes, but it was good to know. --- .gitignore | 1 + configure.ac | 7 +++ tests/c-api/Makefile.am | 20 +++++++++ tests/c-api/test-dlopen.c | 94 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 tests/c-api/test-dlopen.c diff --git a/.gitignore b/.gitignore index b4a8ed187..3e8e7cfca 100644 --- a/.gitignore +++ b/.gitignore @@ -483,6 +483,7 @@ Makefile.in /tests/c-api/test-config /tests/c-api/test-create-handle /tests/c-api/test-debug-to-file +/tests/c-api/test-dlopen /tests/c-api/test-environment /tests/c-api/test-event-string /tests/c-api/test*.img diff --git a/configure.ac b/configure.ac index 28bf541dc..aa2da0c6c 100644 --- a/configure.ac +++ b/configure.ac @@ -581,6 +581,13 @@ AC_ARG_WITH([extra-packages], [EXTRA_PACKAGES=]) AC_SUBST([EXTRA_PACKAGES]) +dnl Check for libdl/dlopen (optional - only used to test if the library +dnl can be used with libdl). +AC_CHECK_LIB([dl],[dlopen],[have_libdl=yes],[have_libdl=no]) +AC_CHECK_HEADERS([dlfcn.h],[have_dlfcn=yes],[have_dlfcn=no]) +AM_CONDITIONAL([HAVE_LIBDL], + [test "x$have_libdl" = "xyes" && test "x$have_dlfcn" = "xyes"]) + dnl Check for rpcgen and XDR library. rpcgen is optional. AC_CHECK_PROG([RPCGEN],[rpcgen],[rpcgen],[no]) AM_CONDITIONAL([HAVE_RPCGEN],[test "x$RPCGEN" != "xno"]) diff --git a/tests/c-api/Makefile.am b/tests/c-api/Makefile.am index fed19238a..94cdd0ac1 100644 --- a/tests/c-api/Makefile.am +++ b/tests/c-api/Makefile.am @@ -38,11 +38,16 @@ check_PROGRAMS = \ test-environment \ test-pwd \ test-event-string +if HAVE_LIBDL +check_PROGRAMS += \ + test-dlopen +endif TESTS = \ tests \ test-just-header \ test-create-handle \ + test-dlopen \ test-config \ test-add-drive-opts \ test-last-errno \ @@ -52,6 +57,10 @@ TESTS = \ test-debug-to-file \ test-environment \ test-event-string +if HAVE_LIBDL +TESTS += \ + test-dlopen +endif if HAVE_CXX check_PROGRAMS += test-just-header-cxx @@ -130,6 +139,17 @@ test_create_handle_CFLAGS = \ test_create_handle_LDADD = \ $(top_builddir)/src/libguestfs.la +if HAVE_LIBDL +test_dlopen_SOURCES = test-dlopen.c +test_dlopen_CPPFLAGS = \ + -I$(top_srcdir)/src -I$(top_builddir)/src +test_dlopen_CFLAGS = \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) \ + -DLIBRARY=\"$(top_builddir)/src/.libs/libguestfs.so.0\" +test_dlopen_LDADD = \ + -ldl +endif + test_config_SOURCES = test-config.c test_config_CPPFLAGS = \ -I$(top_srcdir)/src -I$(top_builddir)/src diff --git a/tests/c-api/test-dlopen.c b/tests/c-api/test-dlopen.c new file mode 100644 index 000000000..3efd847b0 --- /dev/null +++ b/tests/c-api/test-dlopen.c @@ -0,0 +1,94 @@ +/* libguestfs + * Copyright (C) 2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* Test the library can be loaded and unloaded using dlopen etc. */ + +#include + +#include +#include +#include +#include + +/* We don't need the header file here. */ +typedef struct guestfs_h guestfs_h; + +typedef guestfs_h *(*guestfs_create_t) (void); +typedef const char * (*guestfs_get_program_t) (guestfs_h *); +typedef void (*guestfs_close_t) (guestfs_h *); + +#ifndef LIBRARY +#error "-DLIBRARY was not defined" +#endif + +static void * +read_symbol (void *lib, const char *symbol) +{ + void *symval; + const char *err; + + dlerror (); /* Clear error indicator. */ + symval = dlsym (lib, symbol); + if ((err = dlerror ()) != NULL) { + fprintf (stderr, "could not read symbol: %s: %s\n", symbol, err); + exit (EXIT_FAILURE); + } + return symval; +} + +int +main (int argc, char *argv[]) +{ + void *lib; + guestfs_create_t guestfs_create; + guestfs_get_program_t guestfs_get_program; + guestfs_close_t guestfs_close; + guestfs_h *g; + + if (access (LIBRARY, X_OK) == -1) { + fprintf (stderr, "test skipped because %s cannot be accessed: %m\n", + LIBRARY); + exit (77); + } + + lib = dlopen (LIBRARY, RTLD_LAZY); + if (lib == NULL) { + fprintf (stderr, "could not open %s: %s\n", LIBRARY, dlerror ()); + exit (EXIT_FAILURE); + } + + guestfs_create = read_symbol (lib, "guestfs_create"); + guestfs_get_program = read_symbol (lib, "guestfs_get_program"); + guestfs_close = read_symbol (lib, "guestfs_close"); + + g = guestfs_create (); + if (g == NULL) { + fprintf (stderr, "failed to create handle\n"); + exit (EXIT_FAILURE); + } + printf ("program = %s\n", guestfs_get_program (g)); + + guestfs_close (g); + + if (dlclose (lib) != 0) { + fprintf (stderr, "could not close %s: %s\n", LIBRARY, dlerror ()); + exit (EXIT_FAILURE); + } + + exit (EXIT_SUCCESS); +}