diff options
Diffstat (limited to 'src/libstrongswan/tests/test_runner.c')
-rw-r--r-- | src/libstrongswan/tests/test_runner.c | 121 |
1 files changed, 97 insertions, 24 deletions
diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c index 0b26ee128..5ec4198e7 100644 --- a/src/libstrongswan/tests/test_runner.c +++ b/src/libstrongswan/tests/test_runner.c @@ -22,6 +22,7 @@ #include <collections/array.h> #include <utils/test.h> +#include <stdlib.h> #include <dirent.h> #include <unistd.h> #include <limits.h> @@ -32,31 +33,85 @@ #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; } /** - * Load all available test suites + * Destroy a single test suite and associated data + */ +static void destroy_suite(test_suite_t *suite) +{ + test_case_t *tcase; + + while (array_remove(suite->tcases, 0, &tcase)) + { + array_destroy(tcase->functions); + array_destroy(tcase->fixtures); + } + free(suite); +} + +/** + * Removes and destroys test suites that are not selected. + */ +static void filter_suites(array_t *loaded) +{ + enumerator_t *enumerator, *names; + hashtable_t *selected; + test_suite_t *suite; + char *suites, *name; + + suites = getenv("TESTS_SUITES"); + if (!suites) + { + return; + } + selected = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8); + names = enumerator_create_token(suites, ",", " "); + while (names->enumerate(names, &name)) + { + selected->put(selected, name, name); + } + enumerator = array_create_enumerator(loaded); + while (enumerator->enumerate(enumerator, &suite)) + { + if (!selected->get(selected, suite->name)) + { + array_remove_at(loaded, enumerator); + destroy_suite(suite); + } + } + enumerator->destroy(enumerator); + selected->destroy(selected); + names->destroy(names); +} + +/** + * Load all available test suites, or optionally only selected ones. */ static array_t *load_suites(test_configuration_t configs[], test_runner_init_t init) @@ -91,6 +146,7 @@ static array_t *load_suites(test_configuration_t configs[], array_insert(suites, -1, configs[i].suite()); } } + filter_suites(suites); if (lib->leak_detective) { @@ -112,16 +168,10 @@ static array_t *load_suites(test_configuration_t configs[], static void unload_suites(array_t *suites) { test_suite_t *suite; - test_case_t *tcase; while (array_remove(suites, 0, &suite)) { - while (array_remove(suite->tcases, 0, &tcase)) - { - array_destroy(tcase->functions); - array_destroy(tcase->fixtures); - } - free(suite); + destroy_suite(suite); } array_destroy(suites); } @@ -178,6 +228,9 @@ static bool call_fixture(test_case_t *tcase, bool up) */ static bool pre_test(test_runner_init_t init) { + level_t level = LEVEL_SILENT; + char *verbosity; + library_init(NULL, "test-runner"); /* use non-blocking RNG to generate keys fast */ @@ -185,6 +238,9 @@ static bool pre_test(test_runner_init_t init) "libstrongswan.plugins.random.random", lib->settings->get_str(lib->settings, "libstrongswan.plugins.random.urandom", "/dev/urandom")); + /* same for the gcrypt plugin */ + lib->settings->set_default_str(lib->settings, + "libstrongswan.plugins.gcrypt.quick_random", "yes"); if (lib->leak_detective) { @@ -197,7 +253,12 @@ static bool pre_test(test_runner_init_t init) library_deinit(); return FALSE; } - dbg_default_set_level(LEVEL_SILENT); + verbosity = getenv("TESTS_VERBOSITY"); + if (verbosity) + { + level = atoi(verbosity); + } + dbg_default_set_level(level); return TRUE; } @@ -254,7 +315,7 @@ static void sum_leaks(report_data_t *data, int count, size_t bytes, * Do library cleanup and optionally check for memory leaks */ static bool post_test(test_runner_init_t init, bool check_leaks, - array_t *failures, char *name, int i) + array_t *failures, char *name, int i, int *leaks) { report_data_t data = { .failures = failures, @@ -264,7 +325,15 @@ static bool post_test(test_runner_init_t init, bool check_leaks, if (init) { - init(FALSE); + if (test_restore_point()) + { + init(FALSE); + } + else + { + library_deinit(); + return FALSE; + } } if (check_leaks && lib->leak_detective) { @@ -274,7 +343,8 @@ static bool post_test(test_runner_init_t init, bool check_leaks, } library_deinit(); - return data.leaks != 0; + *leaks = data.leaks; + return TRUE; } /** @@ -346,7 +416,8 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init) { if (pre_test(init)) { - bool ok = FALSE, leaks = FALSE; + bool ok = FALSE; + int leaks = 0; test_setup_timeout(tcase->timeout); @@ -363,9 +434,11 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init) { call_fixture(tcase, FALSE); } - } - leaks = post_test(init, ok, failures, tfun->name, i); + if (!post_test(init, ok, failures, tfun->name, i, &leaks)) + { + ok = FALSE; + } test_setup_timeout(0); |