]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/tests.h
hexdecoct: make unbase64mem and unhexmem always use SIZE_MAX
[thirdparty/systemd.git] / src / shared / tests.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
d2120590
LP
2#pragma once
3
ca7a9afc
ZJS
4#include <stdbool.h>
5
48e98ba5
ZJS
6#include "sd-daemon.h"
7
ee617a4e 8#include "argv-util.h"
5eecb103 9#include "macro.h"
99839c7e 10#include "static-destruct.h"
f1a83e41 11#include "strv.h"
5eecb103 12
8161f608
YW
13static inline void log_set_assert_return_is_criticalp(bool *p) {
14 log_set_assert_return_is_critical(*p);
15}
16
17#define _SAVE_ASSERT_RETURN_IS_CRITICAL(b) \
18 _unused_ _cleanup_(log_set_assert_return_is_criticalp) bool b = \
19 log_get_assert_return_is_critical()
20
21#define SAVE_ASSERT_RETURN_IS_CRITICAL \
22 _SAVE_ASSERT_RETURN_IS_CRITICAL(UNIQ_T(saved, UNIQ))
23
24#define ASSERT_RETURN_IS_CRITICAL(b, expr) \
25 ({ \
26 SAVE_ASSERT_RETURN_IS_CRITICAL; \
27 log_set_assert_return_is_critical(b); \
28 expr; \
29 })
30
31#define ASSERT_RETURN_EXPECTED(expr) ASSERT_RETURN_IS_CRITICAL(false, expr)
32#define ASSERT_RETURN_EXPECTED_SE(expr) ASSERT_RETURN_EXPECTED(assert_se(expr));
33
5eecb103
ZJS
34static inline bool manager_errno_skip_test(int r) {
35 return IN_SET(abs(r),
36 EPERM,
37 EACCES,
38 EADDRINUSE,
39 EHOSTDOWN,
40 ENOENT,
41 ENOMEDIUM /* cannot determine cgroup */
42 );
43}
44
d2120590 45char* setup_fake_runtime_dir(void);
64ad9e08 46int enter_cgroup_subroot(char **ret_cgroup);
61ff7397 47int enter_cgroup_root(char **ret_cgroup);
7b432953 48int get_testdata_dir(const char *suffix, char **ret);
49cdae63 49const char* get_catalog_dir(void);
0cf29baa 50bool slow_tests_enabled(void);
6d7c4033 51void test_setup_logging(int level);
678fbf7e
YW
52
53#define log_tests_skipped(fmt, ...) \
54 ({ \
55 log_notice("%s: " fmt ", skipping tests.", \
56 program_invocation_short_name, \
57 ##__VA_ARGS__); \
58 EXIT_TEST_SKIP; \
59 })
60
61#define log_tests_skipped_errno(error, fmt, ...) \
62 ({ \
63 log_notice_errno(error, \
64 "%s: " fmt ", skipping tests: %m", \
65 program_invocation_short_name, \
66 ##__VA_ARGS__); \
67 EXIT_TEST_SKIP; \
68 })
a4bc3c1d 69
367c47c8
ZJS
70int write_tmpfile(char *pattern, const char *contents);
71
a4bc3c1d 72bool have_namespaces(void);
77abd029
ZJS
73
74/* We use the small but non-trivial limit here */
75#define CAN_MEMLOCK_SIZE (512 * 1024U)
76bool can_memlock(void);
48e98ba5 77
0fdcfa78
DS
78/* Define void* buffer and size_t length variables from a hex string. */
79#define DEFINE_HEX_PTR(name, hex) \
80 _cleanup_free_ void *name = NULL; \
81 size_t name##_len = 0; \
bdd2036e 82 assert_se(unhexmem_full(hex, strlen_ptr(hex), false, &name, &name##_len) >= 0);
0fdcfa78 83
48e98ba5
ZJS
84#define TEST_REQ_RUNNING_SYSTEMD(x) \
85 if (sd_booted() > 0) { \
86 x; \
87 } else { \
0578dfe3 88 printf("systemd not booted, skipping '%s'\n", #x); \
48e98ba5 89 }
4eb0c875
ZJS
90
91/* Provide a convenient way to check if we're running in CI. */
92const char *ci_environment(void);
9cc61546
JJ
93
94typedef struct TestFunc {
4c0acc07
JJ
95 union f {
96 void (*void_func)(void);
97 int (*int_func)(void);
98 } f;
99 const char * const name;
0578dfe3
JJ
100 bool has_ret:1;
101 bool sd_booted:1;
9cc61546
JJ
102} TestFunc;
103
104/* See static-destruct.h for an explanation of how this works. */
0578dfe3 105#define REGISTER_TEST(func, ...) \
a3aff1c4
JJ
106 _Pragma("GCC diagnostic ignored \"-Wattributes\"") \
107 _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _retain_ _variable_no_sanitize_address_ \
4c0acc07
JJ
108 static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
109 .f = (union f) &(func), \
110 .name = STRINGIFY(func), \
111 .has_ret = __builtin_types_compatible_p(typeof((union f){}.int_func), typeof(&(func))), \
0578dfe3 112 ##__VA_ARGS__ \
9cc61546
JJ
113 }
114
115extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
116extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
117
0578dfe3
JJ
118#define TEST(name, ...) \
119 static void test_##name(void); \
120 REGISTER_TEST(test_##name, ##__VA_ARGS__); \
9cc61546
JJ
121 static void test_##name(void)
122
0578dfe3
JJ
123#define TEST_RET(name, ...) \
124 static int test_##name(void); \
125 REGISTER_TEST(test_##name, ##__VA_ARGS__); \
4c0acc07
JJ
126 static int test_##name(void)
127
47a7a4d4
LP
128#define TEST_LOG_FUNC() \
129 log_info("/* %s() */", __func__)
130
4c0acc07 131static inline int run_test_table(void) {
f1a83e41 132 _cleanup_strv_free_ char **tests = NULL;
4c0acc07 133 int r = EXIT_SUCCESS;
f1a83e41
LP
134 bool ran = false;
135 const char *e;
4c0acc07 136
9cc61546 137 if (!__start_SYSTEMD_TEST_TABLE)
4c0acc07 138 return r;
9cc61546 139
f1a83e41
LP
140 e = getenv("TESTFUNCS");
141 if (e) {
142 r = strv_split_full(&tests, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
143 if (r < 0)
144 return log_error_errno(r, "Failed to parse $TESTFUNCS: %m");
145 }
146
147 for (const TestFunc *t = ALIGN_PTR(__start_SYSTEMD_TEST_TABLE);
148 t + 1 <= __stop_SYSTEMD_TEST_TABLE;
149 t = ALIGN_PTR(t + 1)) {
150
151 if (tests && !strv_contains(tests, t->name))
152 continue;
0578dfe3
JJ
153
154 if (t->sd_booted && sd_booted() <= 0) {
155 log_info("/* systemd not booted, skipping %s */", t->name);
156 if (t->has_ret && r == EXIT_SUCCESS)
157 r = EXIT_TEST_SKIP;
158 } else {
159 log_info("/* %s */", t->name);
160
161 if (t->has_ret) {
162 int r2 = t->f.int_func();
163 if (r == EXIT_SUCCESS)
164 r = r2;
165 } else
166 t->f.void_func();
167 }
4c0acc07 168
f1a83e41 169 ran = true;
9cc61546 170 }
4c0acc07 171
f1a83e41
LP
172 if (!ran)
173 return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "No matching tests found.");
174
4c0acc07 175 return r;
9cc61546
JJ
176}
177
e85fdacc
YW
178#define DEFINE_TEST_MAIN_FULL(log_level, intro, outro) \
179 int main(int argc, char *argv[]) { \
180 int (*_intro)(void) = intro; \
181 int (*_outro)(void) = outro; \
182 int _r, _q; \
183 test_setup_logging(log_level); \
184 save_argc_argv(argc, argv); \
185 _r = _intro ? _intro() : EXIT_SUCCESS; \
186 if (_r == EXIT_SUCCESS) \
187 _r = run_test_table(); \
188 _q = _outro ? _outro() : EXIT_SUCCESS; \
189 static_destruct(); \
190 if (_r < 0) \
191 return EXIT_FAILURE; \
192 if (_r != EXIT_SUCCESS) \
193 return _r; \
194 if (_q < 0) \
195 return EXIT_FAILURE; \
196 return _q; \
9cc61546
JJ
197 }
198
e85fdacc
YW
199#define DEFINE_TEST_MAIN_WITH_INTRO(log_level, intro) \
200 DEFINE_TEST_MAIN_FULL(log_level, intro, NULL)
201#define DEFINE_TEST_MAIN(log_level) \
202 DEFINE_TEST_MAIN_FULL(log_level, NULL, NULL)