summaryrefslogtreecommitdiff
path: root/src/libstrongswan/tests/test_runner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/tests/test_runner.c')
-rw-r--r--src/libstrongswan/tests/test_runner.c121
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);