/* Provide a convenient way to check if we're running in CI. */
const char *ci_environment(void);
+
+typedef struct TestFunc {
+ void (*f)(void);
+ const char * const n;
+} 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), \
+ }
+
+extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
+extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
+
+#define TEST(name) \
+ REGISTER_TEST(test_##name); \
+ static void test_##name(void)
+
+static inline void run_test_table(void) {
+ if (!__start_SYSTEMD_TEST_TABLE)
+ return;
+
+ 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();
+ t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
+ }
+}
+
+#define DEFINE_TEST_MAIN \
+ int main(int argc, char *argv[]) { \
+ test_setup_logging(LOG_INFO); \
+ run_test_table(); \
+ return EXIT_SUCCESS; \
+ }
+
+#define DEFINE_CUSTOM_TEST_MAIN(impl) \
+ int main(int argc, char *argv[]) { \
+ test_setup_logging(LOG_INFO); \
+ run_test_table(); \
+ return impl(); \
+ }
#include "macro.h"
#include "tests.h"
-static void test_align_power2(void) {
+TEST(align_power2) {
unsigned long i, p2;
- log_info("/* %s */", __func__);
-
assert_se(ALIGN_POWER2(0) == 0);
assert_se(ALIGN_POWER2(1) == 1);
assert_se(ALIGN_POWER2(2) == 2);
}
}
-static void test_max(void) {
+TEST(max) {
static const struct {
int a;
int b[CONST_MAX(10, 100)];
void *p = (void *)str;
void *q = (void *)&str[16];
- log_info("/* %s */", __func__);
-
assert_cc(sizeof(val1.b) == sizeof(int) * 100);
/* CONST_MAX returns (void) instead of a value if the passed arguments
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
#endif
-static void test_container_of(void) {
+TEST(container_of) {
struct mytype {
uint8_t pad1[3];
uint64_t v1;
uint32_t v2;
} myval = { };
- log_info("/* %s */", __func__);
-
assert_cc(sizeof(myval) >= 17);
assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
#pragma GCC diagnostic pop
-static void test_div_round_up(void) {
+TEST(div_round_up) {
int div;
- log_info("/* %s */", __func__);
-
/* basic tests */
assert_se(DIV_ROUND_UP(0, 8) == 0);
assert_se(DIV_ROUND_UP(1, 8) == 1);
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
}
-static void test_ptr_to_int(void) {
- log_info("/* %s */", __func__);
-
+TEST(ptr_to_int) {
/* Primary reason to have this test is to validate that pointers are large enough to hold entire int range */
assert_se(PTR_TO_INT(INT_TO_PTR(0)) == 0);
assert_se(PTR_TO_INT(INT_TO_PTR(1)) == 1);
assert_se(PTR_TO_INT(INT_TO_PTR(INT_MIN)) == INT_MIN);
}
-static void test_in_set(void) {
- log_info("/* %s */", __func__);
-
+TEST(in_set) {
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
assert_se(IN_SET(2, 1, 2, 3, 4));
assert_se(!IN_SET(0, 1, 2, 3, 4));
}
-static void test_foreach_pointer(void) {
+TEST(foreach_pointer) {
int a, b, c, *i;
size_t k = 0;
- log_info("/* %s */", __func__);
-
FOREACH_POINTER(i, &a, &b, &c) {
switch (k) {
assert_se(k == 11);
}
-static void test_align_to(void) {
- log_info("/* %s */", __func__);
-
+TEST(align_to) {
assert_se(ALIGN_TO(0, 1) == 0);
assert_se(ALIGN_TO(1, 1) == 1);
assert_se(ALIGN_TO(2, 1) == 2);
assert_cc(__builtin_types_compatible_p(typeof(CONST_ALIGN_TO(SIZE_MAX, 512)), void));
}
-static void test_flags(void) {
+TEST(flags) {
enum {
F1 = 1 << 0,
F2 = 1 << 1,
};
unsigned n, f;
- log_info("/* %s */", __func__);
-
assert_se(FLAGS_SET(0, 0));
assert_se(FLAGS_SET(F1, F1));
assert_se(FLAGS_SET(F1 | F2, F1));
assert_se(f == F2);
}
-int main(int argc, char *argv[]) {
- test_setup_logging(LOG_INFO);
-
- test_align_power2();
- test_max();
- test_container_of();
- test_div_round_up();
- test_in_set();
- test_foreach_pointer();
- test_ptr_to_int();
- test_align_to();
- test_flags();
-
- return 0;
-}
+DEFINE_TEST_MAIN;