From: Martin Willi Date: Thu, 3 Apr 2014 10:25:38 +0000 (+0200) Subject: unit-tests: Support testable functions on Windows, avoid weak GCC symbols X-Git-Tag: 5.2.0dr6~24^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c34c1b3afb82bc4a4fabf6a4b3d90b5906e4885;p=thirdparty%2Fstrongswan.git unit-tests: Support testable functions on Windows, avoid weak GCC symbols Instead of using weak symbols, we use dlsym() on Windows to find an arbitrary symbol in libtest to detect its linkage. Instead of creating the associated hashtable in the test runner, we maintain it in libstrongswan, making it significantly simpler. --- diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c index 63d79199f5..443c0ae137 100644 --- a/src/libstrongswan/tests/test_runner.c +++ b/src/libstrongswan/tests/test_runner.c @@ -35,35 +35,12 @@ #define TTY(color) tty_escape_get(2, TTY_FG_##color) /** - * Initialize the lookup table for testable functions (defined in - * libstrongswan). We don't use the constructor attribute as the order can't - * really be defined (clang does not support it and gcc does not adhere to it in - * the monolithic build). The function here is a weak symbol in libstrongswan. + * A global symbol indicating libtest linkage */ -void testable_functions_create() -{ - if (!testable_functions) - { - /* as this is executed before chunk_hash() seed initialization used - * by hashtables, we enforce seeding it here. */ - chunk_hash_seed(); - testable_functions = hashtable_create(hashtable_hash_str, - hashtable_equals_str, 8); - } -} - -/** - * Destroy the lookup table for testable functions - */ -static void testable_functions_destroy() __attribute__ ((destructor)); -static void testable_functions_destroy() -{ - DESTROY_IF(testable_functions); - /* if leak detective is enabled plugins are not actually unloaded, which - * means their destructor is called AFTER this one when the process - * terminates, make sure this does not crash */ - testable_functions = NULL; -} +#ifdef WIN32 +__declspec(dllexport) +#endif +bool test_runner_available = TRUE; /** * Destroy a single test suite and associated data diff --git a/src/libstrongswan/utils/test.c b/src/libstrongswan/utils/test.c index 624ac4b347..0b0a80f424 100644 --- a/src/libstrongswan/utils/test.c +++ b/src/libstrongswan/utils/test.c @@ -20,13 +20,23 @@ /** * A collection of testable functions */ -hashtable_t *testable_functions; +static hashtable_t *functions = NULL; + +#ifndef WIN32 +bool test_runner_available __attribute__((weak)); +#endif /** - * The function that actually initializes the hash table above. Provided - * by the test runner. + * Check if we have libtest linkage and need testable functions */ -void testable_functions_create() __attribute__((weak)); +static bool has_libtest_linkage() +{ +#ifdef WIN32 + return dlsym(RTLD_DEFAULT, "test_runner_available"); +#else + return test_runner_available; +#endif +} /* * Described in header. @@ -35,33 +45,48 @@ void testable_function_register(char *name, void *fn) { bool old = FALSE; - if (!testable_functions_create) - { /* not linked to the test runner */ - return; - } - else if (!fn && !testable_functions) - { /* ignore as testable_functions has already been destroyed */ - return; - } - if (lib && lib->leak_detective) { old = lib->leak_detective->set_state(lib->leak_detective, FALSE); } - if (!testable_functions) - { - testable_functions_create(); - } - if (fn) - { - testable_functions->put(testable_functions, name, fn); - } - else + + if (has_libtest_linkage()) { - testable_functions->remove(testable_functions, name); + if (!functions) + { + chunk_hash_seed(); + functions = hashtable_create(hashtable_hash_str, + hashtable_equals_str, 8); + } + if (fn) + { + functions->put(functions, name, fn); + } + else + { + functions->remove(functions, name); + if (functions->get_count(functions) == 0) + { + functions->destroy(functions); + functions = NULL; + } + } } + if (lib && lib->leak_detective) { lib->leak_detective->set_state(lib->leak_detective, old); } } + +/* + * Described in header. + */ +void* testable_function_get(char *name) +{ + if (functions) + { + return functions->get(functions, name); + } + return NULL; +} diff --git a/src/libstrongswan/utils/test.h b/src/libstrongswan/utils/test.h index a1b2a2d9b9..f9a84713e2 100644 --- a/src/libstrongswan/utils/test.h +++ b/src/libstrongswan/utils/test.h @@ -24,19 +24,20 @@ #include "collections/hashtable.h" /** - * Collection of testable functions. + * Register a (possibly static) function so that it can be called from tests. * - * @note Is initialized only if libtest is loaded. + * @param name name (namespace/function) + * @param fn function to register (set to NULL to unregister) */ -extern hashtable_t *testable_functions; +void testable_function_register(char *name, void *fn); /** - * Register a (possibly static) function so that it can be called from tests. + * Find a previously registered testable function. * * @param name name (namespace/function) - * @param fn function to register (set to NULL to unregister) + * @return function, NULL if not found */ -void testable_function_register(char *name, void *fn); +void* testable_function_get(char *name); /** * Macro to automatically register/unregister a function that can be called @@ -82,10 +83,7 @@ static ret (*TEST_##ns##name)(__VA_ARGS__); */ #define TEST_FUNCTION(ns, name, ...) \ ({ \ - if (testable_functions) \ - { \ - TEST_##ns##name = testable_functions->get(testable_functions, #ns "/" #name); \ - } \ + TEST_##ns##name = testable_function_get( #ns "/" #name); \ if (!TEST_##ns##name) \ { \ test_fail_msg(__FILE__, __LINE__, "function " #name " (" #ns ") not found"); \