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)
/**
* 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)));
static void testable_functions_create()
void testable_functions_create()
{
testable_functions = hashtable_create(hashtable_hash_str,
hashtable_equals_str, 8);
if (!testable_functions)
{
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(1000)));
static void testable_functions_destroy() __attribute__ ((destructor));
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
* means their destructor is called AFTER this one when the process
* terminates, even though the priority says differently, make sure this
* does not crash */
* terminates, make sure this does not crash */
testable_functions = NULL;
}

View File

@ -22,29 +22,46 @@
*/
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.
*/
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;
if (lib->leak_detective)
{
old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
}
if (fn)
{
testable_functions->put(testable_functions, name, fn);
}
else
{
testable_functions->remove(testable_functions, name);
}
if (lib->leak_detective)
{
lib->leak_detective->set_state(lib->leak_detective, old);
}
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
{
testable_functions->remove(testable_functions, name);
}
if (lib && lib->leak_detective)
{
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
*/
#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() \
{ \
testable_function_register(#ns "/" #fn, fn); \