unit-tests: Change how hashtable for testable functions is created

Because GCC does not adhere to the priorities defined for constructors
when building with --enable-monolithic (not sure if it was just luck
that it worked in non-monolithic mode - anyway, it's not very portable)
function registration would fail because the hashtable would not be
created yet.
This commit is contained in:
Tobias Brunner 2014-02-28 17:08:39 +01:00
parent d151cd283e
commit f51169eb09
3 changed files with 49 additions and 28 deletions

View File

@ -32,26 +32,30 @@
#define TTY(color) tty_escape_get(2, TTY_FG_##color) #define TTY(color) tty_escape_get(2, TTY_FG_##color)
/** /**
* Initialize the lookup table for testable functions (defined in libstrongswan) * 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.
*/ */
static void testable_functions_create() __attribute__ ((constructor(1000))); void testable_functions_create()
static void testable_functions_create()
{ {
testable_functions = hashtable_create(hashtable_hash_str, if (!testable_functions)
hashtable_equals_str, 8); {
testable_functions = hashtable_create(hashtable_hash_str,
hashtable_equals_str, 8);
}
} }
/** /**
* Destroy the lookup table for testable functions * Destroy the lookup table for testable functions
*/ */
static void testable_functions_destroy() __attribute__ ((destructor(1000))); static void testable_functions_destroy() __attribute__ ((destructor));
static void testable_functions_destroy() static void testable_functions_destroy()
{ {
testable_functions->destroy(testable_functions); DESTROY_IF(testable_functions);
/* if leak detective is enabled plugins are not actually unloaded, which /* if leak detective is enabled plugins are not actually unloaded, which
* means their destructor is called AFTER this one when the process * means their destructor is called AFTER this one when the process
* terminates, even though the priority says differently, make sure this * terminates, make sure this does not crash */
* does not crash */
testable_functions = NULL; testable_functions = NULL;
} }

View File

@ -22,29 +22,46 @@
*/ */
hashtable_t *testable_functions; hashtable_t *testable_functions;
/**
* The function that actually initializes the hash table above. Provided
* by the test runner.
*/
void testable_functions_create() __attribute__((weak));
/* /*
* Described in header. * Described in header.
*/ */
void testable_function_register(char *name, void *fn) void testable_function_register(char *name, void *fn)
{ {
if (testable_functions) 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)
{ {
bool old = FALSE; old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
if (lib->leak_detective) }
{ if (!testable_functions)
old = lib->leak_detective->set_state(lib->leak_detective, FALSE); {
} testable_functions_create();
if (fn) }
{ if (fn)
testable_functions->put(testable_functions, name, fn); {
} testable_functions->put(testable_functions, name, fn);
else }
{ else
testable_functions->remove(testable_functions, name); {
} testable_functions->remove(testable_functions, name);
if (lib->leak_detective) }
{ if (lib && lib->leak_detective)
lib->leak_detective->set_state(lib->leak_detective, old); {
} lib->leak_detective->set_state(lib->leak_detective, old);
} }
} }

View File

@ -51,7 +51,7 @@ void testable_function_register(char *name, void *fn);
* @param fn function to register * @param fn function to register
*/ */
#define EXPORT_FUNCTION_FOR_TESTS(ns, fn) \ #define EXPORT_FUNCTION_FOR_TESTS(ns, fn) \
static void testable_function_register_##fn() __attribute__ ((constructor(2000))); \ static void testable_function_register_##fn() __attribute__ ((constructor)); \
static void testable_function_register_##fn() \ static void testable_function_register_##fn() \
{ \ { \
testable_function_register(#ns "/" #fn, fn); \ testable_function_register(#ns "/" #fn, fn); \