]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-test: Add test_fatal_set_callback()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 18 Jan 2021 12:46:46 +0000 (13:46 +0100)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 18 Jan 2021 13:50:16 +0000 (14:50 +0100)
src/lib-test/test-common.c
src/lib-test/test-common.h

index 1c3ce53193b4291fec636d5a1c2860cfb10d0658..71d7c0a65644a6a66acc2d4384e68f17a0d382a5 100644 (file)
@@ -20,6 +20,8 @@ static unsigned int failure_count;
 static unsigned int total_count;
 static unsigned int expected_errors;
 static char *expected_error_str, *expected_fatal_str;
+static test_fatal_callback_t *test_fatal_callback;
+static void *test_fatal_context;
 
 void test_begin(const char *name)
 {
@@ -229,6 +231,14 @@ void test_expect_fatal_string(const char *substr)
        expected_fatal_str = i_strdup(substr);
 }
 
+#undef test_fatal_set_callback
+void test_fatal_set_callback(test_fatal_callback_t *callback, void *context)
+{
+       i_assert(test_fatal_callback == NULL);
+       test_fatal_callback = callback;
+       test_fatal_context = context;
+}
+
 static void ATTR_FORMAT(2, 0) ATTR_NORETURN
 test_fatal_handler(const struct failure_context *ctx,
                   const char *format, va_list args)
@@ -243,6 +253,12 @@ test_fatal_handler(const struct failure_context *ctx,
        va_end(args);
 
        if (suppress) {
+               if (test_fatal_callback != NULL) {
+                       test_fatal_callback(test_fatal_context);
+                       test_fatal_callback = NULL;
+                       test_fatal_context = NULL;
+               }
+
                i_set_fatal_handler(test_fatal_handler);
                longjmp(fatal_jmpbuf, 1);
        } else {
index 3e4d745e84427e7fa7aebb4ba3eea207896549b2..424944f244147c7f1a9648a18701361f630ae821 100644 (file)
@@ -87,6 +87,8 @@ enum fatal_test_state {
    FATAL_TEST_FINISHED or FATAL_TEST_ABORT is returned. */
 typedef enum fatal_test_state test_fatal_func_t(unsigned int stage);
 
+typedef void test_fatal_callback_t(void *context);
+
 struct named_fatal {
        const char *name;
        test_fatal_func_t *func;
@@ -98,6 +100,14 @@ int test_run_named_with_fatals(const char *match, const struct named_test tests[
 
 /* Require the Fatal/Panic string to match this or the fatal test fails. */
 void test_expect_fatal_string(const char *substr);
+/* Call the specified callback when a fatal is being triggered. This is mainly
+   intended to allow freeing memory so valgrind won't complain about memory
+   leaks. */
+void test_fatal_set_callback(test_fatal_callback_t *callback, void *context);
+#define test_fatal_set_callback(callback, context) \
+       test_fatal_set_callback(1 ? (test_fatal_callback_t *)callback : \
+               CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+               context)
 
 #define FATAL_DECL(x) enum fatal_test_state x(unsigned int);
 #define FATAL_NAMELESS(x) x, /* Were you to want to use the X trick but not name the tests */