From 4c0acc0761aae0370e20e118b9db3b704e9045cd Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Thu, 25 Nov 2021 10:27:51 +0100
Subject: [PATCH] test: Add TEST_RET macro

This declares a test function whose return code will be passed from
main(). The first test that does not return EXIT_SUCCESS wins.

Conflict:NA
Reference:https://github.com/systemd/systemd/commit/4c0acc0761aae0370e20e118b9db3b704e9045cd

---
 src/shared/tests.h | 54 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/src/shared/tests.h b/src/shared/tests.h
index 872b9b2d6c..d1c96ef35b 100644
--- a/src/shared/tests.h
+++ b/src/shared/tests.h
@@ -46,46 +46,68 @@ bool can_memlock(void);
 const char *ci_environment(void);
 
 typedef struct TestFunc {
-        void (*f)(void);
-        const char * const n;
+        union f {
+                void (*void_func)(void);
+                int (*int_func)(void);
+        } f;
+        const char * const name;
+        bool has_ret;
 } TestFunc;
 
 /* See static-destruct.h for an explanation of how this works. */
-#define REGISTER_TEST(func)                                                              \
-        static void func(void);                                                          \
-        _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
-        static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = {                  \
-                .f = &(func),                                                            \
-                .n = STRINGIFY(func),                                                    \
+#define REGISTER_TEST(func)                                                                             \
+        _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_                \
+        static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = {                                 \
+                .f = (union f) &(func),                                                                 \
+                .name = STRINGIFY(func),                                                                \
+                .has_ret = __builtin_types_compatible_p(typeof((union f){}.int_func), typeof(&(func))), \
         }
 
 extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
 extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
 
-#define TEST(name)                  \
-        REGISTER_TEST(test_##name); \
+#define TEST(name)                     \
+        static void test_##name(void); \
+        REGISTER_TEST(test_##name);    \
         static void test_##name(void)
 
-static inline void run_test_table(void) {
+#define TEST_RET(name)                \
+        static int test_##name(void); \
+        REGISTER_TEST(test_##name);   \
+        static int test_##name(void)
+
+static inline int run_test_table(void) {
+        int r = EXIT_SUCCESS;
+
         if (!__start_SYSTEMD_TEST_TABLE)
-                return;
+                return r;
 
         const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
         while (t < __stop_SYSTEMD_TEST_TABLE) {
-                log_info("/* %s */", t->n);
-                t->f();
+                log_info("/* %s */", t->name);
+
+                if (t->has_ret) {
+                        int r2 = t->f.int_func();
+                        if (r == EXIT_SUCCESS)
+                                r = r2;
+                } else
+                        t->f.void_func();
+
                 t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
         }
+
+        return r;
 }
 
 #define DEFINE_CUSTOM_TEST_MAIN(log_level, intro, outro) \
         int main(int argc, char *argv[]) {               \
+                int _r = EXIT_SUCCESS;                   \
                 test_setup_logging(log_level);           \
                 save_argc_argv(argc, argv);              \
                 intro;                                   \
-                run_test_table();                        \
+                _r = run_test_table();                   \
                 outro;                                   \
-                return EXIT_SUCCESS;                     \
+                return _r;                               \
         }
 
 #define DEFINE_TEST_MAIN(log_level) DEFINE_CUSTOM_TEST_MAIN(log_level, , )
-- 
2.33.0

