From 4c0acc0761aae0370e20e118b9db3b704e9045cd Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 10:27:51 +0100 Subject: [PATCH 1/6] 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. --- 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, , ) From 0578dfe3eb2ceb8571b62a904dec0ddf410f6352 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 10:45:15 +0100 Subject: [PATCH 2/6] test: Add sd_booted condition test to TEST macro Note that this will only report test skips if they use TEST_RET macro. Regular TEST macros can still be skipped, but this will not be reported back to main(); --- src/shared/tests.h | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/shared/tests.h b/src/shared/tests.h index d1c96ef35b..95283e2829 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -39,7 +39,7 @@ bool can_memlock(void); if (sd_booted() > 0) { \ x; \ } else { \ - printf("systemd not booted skipping '%s'\n", #x); \ + printf("systemd not booted, skipping '%s'\n", #x); \ } /* Provide a convenient way to check if we're running in CI. */ @@ -51,29 +51,31 @@ typedef struct TestFunc { int (*int_func)(void); } f; const char * const name; - bool has_ret; + bool has_ret:1; + bool sd_booted:1; } TestFunc; /* See static-destruct.h for an explanation of how this works. */ -#define REGISTER_TEST(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))), \ + ##__VA_ARGS__ \ } extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[]; extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[]; -#define TEST(name) \ - static void test_##name(void); \ - REGISTER_TEST(test_##name); \ +#define TEST(name, ...) \ + static void test_##name(void); \ + REGISTER_TEST(test_##name, ##__VA_ARGS__); \ static void test_##name(void) -#define TEST_RET(name) \ - static int test_##name(void); \ - REGISTER_TEST(test_##name); \ +#define TEST_RET(name, ...) \ + static int test_##name(void); \ + REGISTER_TEST(test_##name, ##__VA_ARGS__); \ static int test_##name(void) static inline int run_test_table(void) { @@ -84,14 +86,21 @@ static inline int run_test_table(void) { const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*)); while (t < __stop_SYSTEMD_TEST_TABLE) { - 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(); + if (t->sd_booted && sd_booted() <= 0) { + log_info("/* systemd not booted, skipping %s */", t->name); + if (t->has_ret && r == EXIT_SUCCESS) + r = EXIT_TEST_SKIP; + } else { + 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*)); } From 26e555cbbac3e42c6bf625cb655d2070a9d3a825 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 12:05:57 +0100 Subject: [PATCH 3/6] test: Convert to TEST/TEST_RET macros Note that test-cgroup-mask, test-cgroup-unit-default and test-unit-name will now report being skipped instead of reporting success if not run under systemd. --- src/test/test-acl-util.c | 8 +- src/test/test-cgroup-mask.c | 15 +--- src/test/test-cgroup-unit-default.c | 12 +-- src/test/test-cgroup-util.c | 63 +++++--------- src/test/test-load-fragment.c | 54 +++++------- src/test/test-sleep.c | 51 +++++------ src/test/test-unit-name.c | 126 +++++++--------------------- src/test/test-unit-serialize.c | 26 +++--- 8 files changed, 109 insertions(+), 246 deletions(-) diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c index 37c8265268..cdce5ccef1 100644 --- a/src/test/test-acl-util.c +++ b/src/test/test-acl-util.c @@ -14,15 +14,13 @@ #include "tmpfile-util.h" #include "user-util.h" -static int test_add_acls_for_user(void) { +TEST_RET(add_acls_for_user) { char fn[] = "/tmp/test-empty.XXXXXX"; _cleanup_close_ int fd = -1; char *cmd; uid_t uid; int r; - log_info("/* %s */", __func__); - fd = mkostemp_safe(fn); assert_se(fd >= 0); @@ -71,6 +69,4 @@ static int test_add_acls_for_user(void) { return 0; } -int main(int argc, char **argv) { - return test_add_acls_for_user(); -} +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c index 415ddf3e98..6058f32b0e 100644 --- a/src/test/test-cgroup-mask.c +++ b/src/test/test-cgroup-mask.c @@ -26,7 +26,7 @@ static void log_cgroup_mask(CGroupMask got, CGroupMask expected) { log_info("Got mask: %s\n", g_store); } -static int test_cgroup_mask(void) { +TEST_RET(cgroup_mask, .sd_booted = true) { _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(manager_freep) Manager *m = NULL; Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf; @@ -138,7 +138,7 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) { assert_se(streq_ptr(b, t)); } -static void test_cg_mask_to_string(void) { +TEST(cg_mask_to_string) { test_cg_mask_to_string_one(0, NULL); test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices bpf-foreign bpf-socket-bind bpf-restrict-network-interfaces"); test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu"); @@ -156,13 +156,4 @@ static void test_cg_mask_to_string(void) { test_cg_mask_to_string_one(CGROUP_MASK_IO|CGROUP_MASK_BLKIO, "io blkio"); } -int main(int argc, char* argv[]) { - int rc = EXIT_SUCCESS; - - test_setup_logging(LOG_DEBUG); - - test_cg_mask_to_string(); - TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask()); - - return rc; -} +DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/test/test-cgroup-unit-default.c b/src/test/test-cgroup-unit-default.c index 0fae2f64cb..4c8de1e382 100644 --- a/src/test/test-cgroup-unit-default.c +++ b/src/test/test-cgroup-unit-default.c @@ -8,7 +8,7 @@ #include "tests.h" #include "unit.h" -static int test_default_memory_low(void) { +TEST_RET(default_memory_low, .sd_booted = true) { _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(manager_freep) Manager *m = NULL; Unit *root, *dml, @@ -135,12 +135,4 @@ static int test_default_memory_low(void) { return 0; } -int main(int argc, char* argv[]) { - int rc = EXIT_SUCCESS; - - test_setup_logging(LOG_DEBUG); - - TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low()); - - return rc; -} +DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index bc5eda61f8..621e68829e 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -28,7 +28,7 @@ static void check_p_d_u(const char *path, int code, const char *result) { assert_se(streq_ptr(unit, result)); } -static void test_path_decode_unit(void) { +TEST(path_decode_unit) { check_p_d_u("getty@tty2.service", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service"); @@ -50,7 +50,7 @@ static void check_p_g_u(const char *path, int code, const char *result) { assert_se(streq_ptr(unit, result)); } -static void test_path_get_unit(void) { +TEST(path_get_unit) { check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service"); check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service"); @@ -74,7 +74,7 @@ static void check_p_g_u_u(const char *path, int code, const char *result) { assert_se(streq_ptr(unit, result)); } -static void test_path_get_user_unit(void) { +TEST(path_get_user_unit) { check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service"); @@ -97,7 +97,7 @@ static void check_p_g_s(const char *path, int code, const char *result) { assert_se(streq_ptr(s, result)); } -static void test_path_get_session(void) { +TEST(path_get_session) { check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2"); check_p_g_s("/session-3.scope", 0, "3"); check_p_g_s("/session-.scope", -ENXIO, NULL); @@ -111,7 +111,7 @@ static void check_p_g_o_u(const char *path, int code, uid_t result) { assert_se(uid == result); } -static void test_path_get_owner_uid(void) { +TEST(path_get_owner_uid) { check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000); check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006); check_p_g_o_u("", -ENXIO, 0); @@ -124,7 +124,7 @@ static void check_p_g_slice(const char *path, int code, const char *result) { assert_se(streq_ptr(s, result)); } -static void test_path_get_slice(void) { +TEST(path_get_slice) { check_p_g_slice("/user.slice", 0, "user.slice"); check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE); check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice"); @@ -141,7 +141,7 @@ static void check_p_g_u_slice(const char *path, int code, const char *result) { assert_se(streq_ptr(s, result)); } -static void test_path_get_user_slice(void) { +TEST(path_get_user_slice) { check_p_g_u_slice("/user.slice", -ENXIO, NULL); check_p_g_u_slice("/foobar", -ENXIO, NULL); check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL); @@ -158,14 +158,14 @@ static void test_path_get_user_slice(void) { check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); } -static void test_get_paths(void) { +TEST(get_paths, .sd_booted = true) { _cleanup_free_ char *a = NULL; assert_se(cg_get_root_path(&a) >= 0); log_info("Root = %s", a); } -static void test_proc(void) { +TEST(proc) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r; @@ -220,7 +220,7 @@ static void test_escape_one(const char *s, const char *r) { assert_se(streq(cg_unescape(b), s)); } -static void test_escape(void) { +TEST(escape, .sd_booted = true) { test_escape_one("foobar", "foobar"); test_escape_one(".foobar", "_.foobar"); test_escape_one("foobar.service", "foobar.service"); @@ -234,7 +234,7 @@ static void test_escape(void) { test_escape_one(".", "_."); } -static void test_controller_is_valid(void) { +TEST(controller_is_valid) { assert_se(cg_controller_is_valid("foobar")); assert_se(cg_controller_is_valid("foo_bar")); assert_se(cg_controller_is_valid("name=foo")); @@ -260,7 +260,7 @@ static void test_slice_to_path_one(const char *unit, const char *path, int error assert_se(streq_ptr(ret, path)); } -static void test_slice_to_path(void) { +TEST(slice_to_path) { test_slice_to_path_one("foobar.slice", "foobar.slice", 0); test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0); test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL); @@ -292,16 +292,14 @@ static void test_shift_path_one(const char *raw, const char *root, const char *s assert_se(streq(s, shifted)); } -static void test_shift_path(void) { - +TEST(shift_path) { test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "/foobar", "/waldo"); test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo"); } -static void test_mask_supported(void) { - +TEST(mask_supported, .sd_booted = true) { CGroupMask m; CGroupController c; @@ -311,7 +309,7 @@ static void test_mask_supported(void) { printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); } -static void test_is_cgroup_fs(void) { +TEST(is_cgroup_fs, .sd_booted = true) { struct statfs sfs; assert_se(statfs("/sys/fs/cgroup", &sfs) == 0); if (is_temporary_fs(&sfs)) @@ -319,7 +317,7 @@ static void test_is_cgroup_fs(void) { assert_se(is_cgroup_fs(&sfs)); } -static void test_fd_is_cgroup_fs(void) { +TEST(fd_is_cgroup_fs, .sd_booted = true) { int fd; fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); @@ -333,7 +331,7 @@ static void test_fd_is_cgroup_fs(void) { fd = safe_close(fd); } -static void test_cg_tests(void) { +TEST(cg_tests) { int all, hybrid, systemd, r; r = cg_unified(); @@ -364,7 +362,7 @@ static void test_cg_tests(void) { assert_se(!systemd); } -static void test_cg_get_keyed_attribute(void) { +TEST(cg_get_keyed_attribute) { _cleanup_free_ char *val = NULL; char *vals3[3] = {}, *vals3a[3] = {}; int i, r; @@ -429,27 +427,4 @@ static void test_cg_get_keyed_attribute(void) { } } -int main(void) { - test_setup_logging(LOG_DEBUG); - - test_path_decode_unit(); - test_path_get_unit(); - test_path_get_user_unit(); - test_path_get_session(); - test_path_get_owner_uid(); - test_path_get_slice(); - test_path_get_user_slice(); - TEST_REQ_RUNNING_SYSTEMD(test_get_paths()); - test_proc(); - TEST_REQ_RUNNING_SYSTEMD(test_escape()); - test_controller_is_valid(); - test_slice_to_path(); - test_shift_path(); - TEST_REQ_RUNNING_SYSTEMD(test_mask_supported()); - TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs()); - TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs()); - test_cg_tests(); - test_cg_get_keyed_attribute(); - - return 0; -} +DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c index 124832cdc9..e878979a89 100644 --- a/src/test/test-load-fragment.c +++ b/src/test/test-load-fragment.c @@ -30,7 +30,7 @@ /* Nontrivial value serves as a placeholder to check that parsing function (didn't) change it */ #define CGROUP_LIMIT_DUMMY 3 -static int test_unit_file_get_set(void) { +TEST_RET(unit_file_get_set) { int r; Hashmap *h; UnitFileList *p; @@ -78,7 +78,7 @@ static void check_execcommand(ExecCommand *c, assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore); } -static void test_config_parse_exec(void) { +TEST(config_parse_exec) { /* int config_parse_exec( const char *unit, const char *filename, @@ -422,7 +422,7 @@ static void test_config_parse_exec(void) { exec_command_free_list(c); } -static void test_config_parse_log_extra_fields(void) { +TEST(config_parse_log_extra_fields) { /* int config_parse_log_extra_fields( const char *unit, const char *filename, @@ -486,7 +486,7 @@ static void test_config_parse_log_extra_fields(void) { log_info("/* %s – bye */", __func__); } -static void test_install_printf(void) { +TEST(install_printf, .sd_booted = true) { char name[] = "name.service", path[] = "/run/systemd/system/name.service"; UnitFileInstallInfo i = { .name = name, .path = path, }; @@ -565,7 +565,7 @@ static uint64_t make_cap(int cap) { return ((uint64_t) 1ULL << (uint64_t) cap); } -static void test_config_parse_capability_set(void) { +TEST(config_parse_capability_set) { /* int config_parse_capability_set( const char *unit, const char *filename, @@ -618,7 +618,7 @@ static void test_config_parse_capability_set(void) { assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); } -static void test_config_parse_rlimit(void) { +TEST(config_parse_rlimit) { struct rlimit * rl[_RLIMIT_MAX] = {}; assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0); @@ -732,7 +732,7 @@ static void test_config_parse_rlimit(void) { rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]); } -static void test_config_parse_pass_environ(void) { +TEST(config_parse_pass_environ) { /* int config_parse_pass_environ( const char *unit, const char *filename, @@ -769,11 +769,11 @@ static void test_config_parse_pass_environ(void) { assert_se(streq(passenv[0], "normal_name")); } -static void test_unit_dump_config_items(void) { +TEST(unit_dump_config_items) { unit_dump_config_items(stdout); } -static void test_config_parse_memory_limit(void) { +TEST(config_parse_memory_limit) { /* int config_parse_memory_limit( const char *unit, const char *filename, @@ -829,7 +829,7 @@ static void test_config_parse_memory_limit(void) { } -static void test_contains_instance_specifier_superset(void) { +TEST(contains_instance_specifier_superset) { assert_se(contains_instance_specifier_superset("foobar@a%i")); assert_se(contains_instance_specifier_superset("foobar@%ia")); assert_se(contains_instance_specifier_superset("foobar@%n")); @@ -851,7 +851,7 @@ static void test_contains_instance_specifier_superset(void) { assert_se(!contains_instance_specifier_superset("@%a%b")); } -static void test_unit_is_recursive_template_dependency(void) { +TEST(unit_is_recursive_template_dependency) { _cleanup_(manager_freep) Manager *m = NULL; Unit *u; int r; @@ -894,29 +894,15 @@ static void test_unit_is_recursive_template_dependency(void) { assert_se(unit_is_likely_recursive_template_dependency(u, "foobar@foobar@123.mount", "foobar@%n.mount") == 0); } -int main(int argc, char *argv[]) { +DEFINE_CUSTOM_TEST_MAIN( + LOG_INFO, + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; - int r; + ({ + if (enter_cgroup_subroot(NULL) == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); - test_setup_logging(LOG_INFO); + assert_se(runtime_dir = setup_fake_runtime_dir()); + }), - r = enter_cgroup_subroot(NULL); - if (r == -ENOMEDIUM) - return log_tests_skipped("cgroupfs not available"); - - assert_se(runtime_dir = setup_fake_runtime_dir()); - - r = test_unit_file_get_set(); - test_config_parse_exec(); - test_config_parse_log_extra_fields(); - test_config_parse_capability_set(); - test_config_parse_rlimit(); - test_config_parse_pass_environ(); - TEST_REQ_RUNNING_SYSTEMD(test_install_printf()); - test_unit_dump_config_items(); - test_config_parse_memory_limit(); - test_contains_instance_specifier_superset(); - test_unit_is_recursive_template_dependency(); - - return r; -} + /* no outro */); diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c index 7b982c2df8..183ad4f7b7 100644 --- a/src/test/test-sleep.c +++ b/src/test/test-sleep.c @@ -17,9 +17,8 @@ #include "tests.h" #include "util.h" -static void test_parse_sleep_config(void) { +TEST(parse_sleep_config) { _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; - log_info("/* %s */", __func__); assert_se(parse_sleep_config(&sleep_config) == 0); @@ -43,7 +42,7 @@ static void test_parse_sleep_config(void) { log_debug(" states: %s", hys); } -static int test_fiemap(const char *path) { +static int test_fiemap_one(const char *path) { _cleanup_free_ struct fiemap *fiemap = NULL; _cleanup_close_ int fd = -1; int r; @@ -71,7 +70,20 @@ static int test_fiemap(const char *path) { return 0; } -static void test_sleep(void) { +TEST_RET(fiemap) { + int r = 0; + + assert_se(test_fiemap_one(saved_argv[0]) == 0); + for (int i = 1; i < saved_argc; i++) { + int k = test_fiemap_one(saved_argv[i]); + if (r == 0) + r = k; + } + + return r; +} + +TEST(sleep) { _cleanup_strv_free_ char **standby = strv_new("standby"), **mem = strv_new("mem"), @@ -83,8 +95,6 @@ static void test_sleep(void) { **freeze = strv_new("freeze"); int r; - log_info("/* %s */", __func__); - printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot())); log_info("/= individual sleep modes =/"); @@ -108,25 +118,10 @@ static void test_sleep(void) { log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); } -int main(int argc, char* argv[]) { - int i, r = 0, k; - - test_setup_logging(LOG_DEBUG); - - if (getuid() != 0) - log_warning("This program is unlikely to work for unprivileged users"); - - test_parse_sleep_config(); - test_sleep(); - - if (argc <= 1) - assert_se(test_fiemap(argv[0]) == 0); - else - for (i = 1; i < argc; i++) { - k = test_fiemap(argv[i]); - if (r == 0) - r = k; - } - - return r; -} +DEFINE_CUSTOM_TEST_MAIN( + LOG_DEBUG, + ({ + if (getuid() != 0) + log_warning("This program is unlikely to work for unprivileged users"); + }), + /* no outro */); diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index 665e7b7933..6bde9e090d 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -33,9 +33,7 @@ static void test_unit_name_is_valid_one(const char *name, UnitNameFlags flags, b assert_se(unit_name_is_valid(name, flags) == expected); } -static void test_unit_name_is_valid(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_is_valid) { test_unit_name_is_valid_one("foo.service", UNIT_NAME_ANY, true); test_unit_name_is_valid_one("foo.service", UNIT_NAME_PLAIN, true); test_unit_name_is_valid_one("foo.service", UNIT_NAME_INSTANCE, false); @@ -91,9 +89,7 @@ static void test_unit_name_replace_instance_one(const char *pattern, const char assert_se(streq_ptr(t, expected)); } -static void test_unit_name_replace_instance(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_replace_instance) { test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL); @@ -119,9 +115,7 @@ static void test_unit_name_from_path_one(const char *path, const char *suffix, c } } -static void test_unit_name_from_path(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_from_path) { test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0); test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0); test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0); @@ -149,9 +143,7 @@ static void test_unit_name_from_path_instance_one(const char *pattern, const cha } } -static void test_unit_name_from_path_instance(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_from_path_instance) { test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0); test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0); test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0); @@ -170,9 +162,7 @@ static void test_unit_name_to_path_one(const char *unit, const char *path, int r assert_se(streq_ptr(path, p)); } -static void test_unit_name_to_path(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_to_path) { test_unit_name_to_path_one("home.mount", "/home", 0); test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0); test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL); @@ -201,9 +191,7 @@ static void test_unit_name_mangle_one(bool allow_globs, const char *pattern, con } } -static void test_unit_name_mangle(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_mangle) { test_unit_name_mangle_one(false, "foo.service", "foo.service", 0); test_unit_name_mangle_one(false, "/home", "home.mount", 1); test_unit_name_mangle_one(false, "/dev/sda", "dev-sda.device", 1); @@ -220,14 +208,12 @@ static void test_unit_name_mangle(void) { test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1); } -static int test_unit_printf(void) { +TEST_RET(unit_printf, .sd_booted = true) { _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL; _cleanup_(manager_freep) Manager *m = NULL; Unit *u; int r; - log_info("/* %s */", __func__); - assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid); assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid); assert_se(host = gethostname_malloc()); @@ -328,9 +314,7 @@ static int test_unit_printf(void) { return 0; } -static void test_unit_instance_is_valid(void) { - log_info("/* %s */", __func__); - +TEST(unit_instance_is_valid) { assert_se(unit_instance_is_valid("fooBar")); assert_se(unit_instance_is_valid("foo-bar")); assert_se(unit_instance_is_valid("foo.stUff")); @@ -343,9 +327,7 @@ static void test_unit_instance_is_valid(void) { assert_se(!unit_instance_is_valid("foo/bar")); } -static void test_unit_prefix_is_valid(void) { - log_info("/* %s */", __func__); - +TEST(unit_prefix_is_valid) { assert_se(unit_prefix_is_valid("fooBar")); assert_se(unit_prefix_is_valid("foo-bar")); assert_se(unit_prefix_is_valid("foo.stUff")); @@ -359,11 +341,9 @@ static void test_unit_prefix_is_valid(void) { assert_se(!unit_prefix_is_valid("@foo-bar")); } -static void test_unit_name_change_suffix(void) { +TEST(unit_name_change_suffix) { char *t; - log_info("/* %s */", __func__); - assert_se(unit_name_change_suffix("foo.mount", ".service", &t) == 0); assert_se(streq(t, "foo.service")); free(t); @@ -373,11 +353,9 @@ static void test_unit_name_change_suffix(void) { free(t); } -static void test_unit_name_build(void) { +TEST(unit_name_build) { char *t; - log_info("/* %s */", __func__); - assert_se(unit_name_build("foo", "bar", ".service", &t) == 0); assert_se(streq(t, "foo@bar.service")); free(t); @@ -391,9 +369,7 @@ static void test_unit_name_build(void) { free(t); } -static void test_slice_name_is_valid(void) { - log_info("/* %s */", __func__); - +TEST(slice_name_is_valid) { assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE)); assert_se( slice_name_is_valid("foo.slice")); assert_se( slice_name_is_valid("foo-bar.slice")); @@ -422,12 +398,10 @@ static void test_slice_name_is_valid(void) { assert_se(!slice_name_is_valid("foo@bar.service")); } -static void test_build_subslice(void) { +TEST(build_subslice) { char *a; char *b; - log_info("/* %s */", __func__); - assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0); assert_se(slice_build_subslice(a, "bar", &b) >= 0); free(a); @@ -449,9 +423,7 @@ static void test_build_parent_slice_one(const char *name, const char *expect, in assert_se(streq_ptr(s, expect)); } -static void test_build_parent_slice(void) { - log_info("/* %s */", __func__); - +TEST(build_parent_slice) { test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0); test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1); test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1); @@ -470,12 +442,10 @@ static void test_build_parent_slice(void) { test_build_parent_slice_one("@.slice", NULL, -EINVAL); } -static void test_unit_name_to_instance(void) { +TEST(unit_name_to_instance) { UnitNameFlags r; char *instance; - log_info("/* %s */", __func__); - r = unit_name_to_instance("foo@bar.service", &instance); assert_se(r == UNIT_NAME_INSTANCE); assert_se(streq(instance, "bar")); @@ -504,11 +474,9 @@ static void test_unit_name_to_instance(void) { assert_se(!instance); } -static void test_unit_name_escape(void) { +TEST(unit_name_escape) { _cleanup_free_ char *r; - log_info("/* %s */", __func__); - r = unit_name_escape("ab+-c.a/bc@foo.service"); assert_se(r); assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service")); @@ -522,9 +490,7 @@ static void test_u_n_t_one(const char *name, const char *expected, int ret) { assert_se(streq_ptr(f, expected)); } -static void test_unit_name_template(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_template) { test_u_n_t_one("foo@bar.service", "foo@.service", 0); test_u_n_t_one("foo.mount", NULL, -EINVAL); } @@ -536,9 +502,7 @@ static void test_unit_name_path_unescape_one(const char *name, const char *path, assert_se(streq_ptr(path, p)); } -static void test_unit_name_path_unescape(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_path_unescape) { test_unit_name_path_unescape_one("foo", "/foo", 0); test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0); test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0); @@ -560,9 +524,7 @@ static void test_unit_name_to_prefix_one(const char *input, int ret, const char assert_se(streq_ptr(k, output)); } -static void test_unit_name_to_prefix(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_to_prefix) { test_unit_name_to_prefix_one("foobar.service", 0, "foobar"); test_unit_name_to_prefix_one("", -EINVAL, NULL); test_unit_name_to_prefix_one("foobar", -EINVAL, NULL); @@ -582,9 +544,7 @@ static void test_unit_name_from_dbus_path_one(const char *input, int ret, const assert_se(streq_ptr(k, output)); } -static void test_unit_name_from_dbus_path(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_from_dbus_path) { test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice"); @@ -870,9 +830,7 @@ static void test_unit_name_from_dbus_path(void) { test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service"); } -static void test_unit_name_prefix_equal(void) { - log_info("/* %s */", __func__); - +TEST(unit_name_prefix_equal) { assert_se(unit_name_prefix_equal("a.service", "a.service")); assert_se(unit_name_prefix_equal("a.service", "a.mount")); assert_se(unit_name_prefix_equal("a@b.service", "a.service")); @@ -886,39 +844,15 @@ static void test_unit_name_prefix_equal(void) { assert_se(!unit_name_prefix_equal("a", "a")); } -int main(int argc, char* argv[]) { +DEFINE_CUSTOM_TEST_MAIN( + LOG_INFO, + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; - int r, rc = 0; + ({ + if (enter_cgroup_subroot(NULL) == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); - test_setup_logging(LOG_INFO); + assert_se(runtime_dir = setup_fake_runtime_dir()); + }), - r = enter_cgroup_subroot(NULL); - if (r == -ENOMEDIUM) - return log_tests_skipped("cgroupfs not available"); - - assert_se(runtime_dir = setup_fake_runtime_dir()); - - test_unit_name_is_valid(); - test_unit_name_replace_instance(); - test_unit_name_from_path(); - test_unit_name_from_path_instance(); - test_unit_name_mangle(); - test_unit_name_to_path(); - TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf()); - test_unit_instance_is_valid(); - test_unit_prefix_is_valid(); - test_unit_name_change_suffix(); - test_unit_name_build(); - test_slice_name_is_valid(); - test_build_subslice(); - test_build_parent_slice(); - test_unit_name_to_instance(); - test_unit_name_escape(); - test_unit_name_template(); - test_unit_name_path_unescape(); - test_unit_name_to_prefix(); - test_unit_name_from_dbus_path(); - test_unit_name_prefix_equal(); - - return rc; -} + /* no outro */); diff --git a/src/test/test-unit-serialize.c b/src/test/test-unit-serialize.c index 9bd634fcbd..899fdc000c 100644 --- a/src/test/test-unit-serialize.c +++ b/src/test/test-unit-serialize.c @@ -23,12 +23,10 @@ static void test_deserialize_exec_command_one(Manager *m, const char *key, const * always rejected with "Current command vanished from the unit file", and we don't leak anything. */ } -static void test_deserialize_exec_command(void) { +TEST(deserialize_exec_command) { _cleanup_(manager_freep) Manager *m = NULL; int r; - log_info("/* %s */", __func__); - r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); if (manager_errno_skip_test(r)) { log_notice_errno(r, "Skipping test: manager_new: %m"); @@ -50,19 +48,15 @@ static void test_deserialize_exec_command(void) { test_deserialize_exec_command_one(m, "control-command", "ExecWhat 11 /a/b c d e", -EINVAL); } -int main(int argc, char *argv[]) { +DEFINE_CUSTOM_TEST_MAIN( + LOG_DEBUG, + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; - int r; + ({ + if (enter_cgroup_subroot(NULL) == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); - test_setup_logging(LOG_DEBUG); + assert_se(runtime_dir = setup_fake_runtime_dir()); + }), - r = enter_cgroup_subroot(NULL); - if (r == -ENOMEDIUM) - return log_tests_skipped("cgroupfs not available"); - - assert_se(runtime_dir = setup_fake_runtime_dir()); - - test_deserialize_exec_command(); - - return EXIT_SUCCESS; -} + /* no outro */); From 353b98020420946549569bd3c6876bf8f0773c2b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 12:27:42 +0100 Subject: [PATCH 4/6] test-barrier: Convert to TEST macro --- src/test/test-barrier.c | 93 ++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c index 6ef2998a56..8998282afb 100644 --- a/src/test/test-barrier.c +++ b/src/test/test-barrier.c @@ -40,7 +40,7 @@ static void sleep_for(usec_t usecs) { } #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \ - static void _FUNCTION(void) { \ + TEST(_FUNCTION) { \ Barrier b = BARRIER_NULL; \ pid_t pid1, pid2; \ \ @@ -100,7 +100,7 @@ static void sleep_for(usec_t usecs) { * pending HUP on the pipe. However, the barrier_sync() prefers reads on the * eventfd, thus we can safely wait on the barrier. */ -TEST_BARRIER(test_barrier_sync, +TEST_BARRIER(barrier_sync, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); @@ -122,7 +122,7 @@ TEST_BARRIER(test_barrier_sync, * succeed as the child hasn't read the parent's barrier, yet. The following * barrier and sync synchronize the exit. */ -TEST_BARRIER(test_barrier_wait_next, +TEST_BARRIER(barrier_wait_next, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME * 10); @@ -148,7 +148,7 @@ TEST_BARRIER(test_barrier_wait_next, * not look at barrier-links so this stall is expected. Thus this test times * out. */ -TEST_BARRIER(test_barrier_wait_next_twice, +TEST_BARRIER(barrier_wait_next_twice, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); @@ -171,7 +171,7 @@ TEST_BARRIER(test_barrier_wait_next_twice, * between both waits. This does not have any effect on the wait so it times out * like the other test. */ -TEST_BARRIER(test_barrier_wait_next_twice_local, +TEST_BARRIER(barrier_wait_next_twice_local, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); @@ -196,7 +196,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_local, * synced wait as the second wait. This works just fine because the local state * has no barriers placed, therefore, the remote is always in sync. */ -TEST_BARRIER(test_barrier_wait_next_twice_sync, +TEST_BARRIER(barrier_wait_next_twice_sync, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); @@ -217,7 +217,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_sync, * synced wait as the second wait. This works just fine because the local state * is in sync with the remote. */ -TEST_BARRIER(test_barrier_wait_next_twice_local_sync, +TEST_BARRIER(barrier_wait_next_twice_local_sync, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); @@ -239,7 +239,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_local_sync, * This tests sync_*() synchronizations and makes sure they work fine if the * local state is behind the remote state. */ -TEST_BARRIER(test_barrier_sync_next, +TEST_BARRIER(barrier_sync_next, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_sync_next(&b)); @@ -265,7 +265,7 @@ TEST_BARRIER(test_barrier_sync_next, * This tests timeouts if sync_*() is used if local barriers are placed but the * remote didn't place any. */ -TEST_BARRIER(test_barrier_sync_next_local, +TEST_BARRIER(barrier_sync_next_local, ({ set_alarm(BASE_TIME); assert_se(barrier_place(&b)); @@ -283,7 +283,7 @@ TEST_BARRIER(test_barrier_sync_next_local, * This is the same as test_barrier_sync_next_local but aborts the sync in the * parent. Therefore, the sync_next() succeeds just fine due to the abortion. */ -TEST_BARRIER(test_barrier_sync_next_local_abort, +TEST_BARRIER(barrier_sync_next_local_abort, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); @@ -299,7 +299,7 @@ TEST_BARRIER(test_barrier_sync_next_local_abort, * Test matched wait_abortion() * This runs wait_abortion() with remote abortion. */ -TEST_BARRIER(test_barrier_wait_abortion, +TEST_BARRIER(barrier_wait_abortion, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_wait_abortion(&b)); @@ -315,7 +315,7 @@ TEST_BARRIER(test_barrier_wait_abortion, * This runs wait_abortion() without any remote abortion going on. It thus must * timeout. */ -TEST_BARRIER(test_barrier_wait_abortion_unmatched, +TEST_BARRIER(barrier_wait_abortion_unmatched, ({ set_alarm(BASE_TIME); assert_se(barrier_wait_abortion(&b)); @@ -331,7 +331,7 @@ TEST_BARRIER(test_barrier_wait_abortion_unmatched, * Test matched wait_abortion() with local abortion * This runs wait_abortion() with local and remote abortion. */ -TEST_BARRIER(test_barrier_wait_abortion_local, +TEST_BARRIER(barrier_wait_abortion_local, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_abort(&b)); @@ -347,7 +347,7 @@ TEST_BARRIER(test_barrier_wait_abortion_local, * Test unmatched wait_abortion() with local abortion * This runs wait_abortion() with only local abortion. This must time out. */ -TEST_BARRIER(test_barrier_wait_abortion_local_unmatched, +TEST_BARRIER(barrier_wait_abortion_local_unmatched, ({ set_alarm(BASE_TIME); assert_se(barrier_abort(&b)); @@ -365,7 +365,7 @@ TEST_BARRIER(test_barrier_wait_abortion_local_unmatched, * Place barrier and sync with the child. The child only exits()s, which should * cause an implicit abortion and wake the parent. */ -TEST_BARRIER(test_barrier_exit, +TEST_BARRIER(barrier_exit, ({ }), TEST_BARRIER_WAIT_SUCCESS(pid1), @@ -382,7 +382,7 @@ TEST_BARRIER(test_barrier_exit, * child-exit. We add a usleep() which triggers the alarm in the parent and * causes the test to time out. */ -TEST_BARRIER(test_barrier_no_exit, +TEST_BARRIER(barrier_no_exit, ({ sleep_for(BASE_TIME * 2); }), @@ -404,7 +404,7 @@ TEST_BARRIER(test_barrier_no_exit, * succeeds. Only if we place one more barrier, we're ahead of the remote, thus * we will fail due to HUP on the pipe. */ -TEST_BARRIER(test_barrier_pending_exit, +TEST_BARRIER(barrier_pending_exit, ({ set_alarm(BASE_TIME * 4); sleep_for(BASE_TIME * 2); @@ -421,44 +421,25 @@ TEST_BARRIER(test_barrier_pending_exit, }), TEST_BARRIER_WAIT_SUCCESS(pid2)); -int main(int argc, char *argv[]) { - int v; - test_setup_logging(LOG_INFO); +DEFINE_CUSTOM_TEST_MAIN( + LOG_INFO, + ({ + if (!slow_tests_enabled()) + return log_tests_skipped("slow tests are disabled"); - if (!slow_tests_enabled()) - return log_tests_skipped("slow tests are disabled"); + /* + * This test uses real-time alarms and sleeps to test for CPU races + * explicitly. This is highly fragile if your system is under load. We + * already increased the BASE_TIME value to make the tests more robust, + * but that just makes the test take significantly longer. Given the recent + * issues when running the test in a virtualized environments, limit it + * to bare metal machines only, to minimize false-positives in CIs. + */ + int v = detect_virtualization(); + if (IN_SET(v, -EPERM, -EACCES)) + return log_tests_skipped("Cannot detect virtualization"); - /* - * This test uses real-time alarms and sleeps to test for CPU races - * explicitly. This is highly fragile if your system is under load. We - * already increased the BASE_TIME value to make the tests more robust, - * but that just makes the test take significantly longer. Given the recent - * issues when running the test in a virtualized environments, limit it - * to bare metal machines only, to minimize false-positives in CIs. - */ - v = detect_virtualization(); - if (IN_SET(v, -EPERM, -EACCES)) - return log_tests_skipped("Cannot detect virtualization"); - - if (v != VIRTUALIZATION_NONE) - return log_tests_skipped("This test requires a baremetal machine"); - - test_barrier_sync(); - test_barrier_wait_next(); - test_barrier_wait_next_twice(); - test_barrier_wait_next_twice_sync(); - test_barrier_wait_next_twice_local(); - test_barrier_wait_next_twice_local_sync(); - test_barrier_sync_next(); - test_barrier_sync_next_local(); - test_barrier_sync_next_local_abort(); - test_barrier_wait_abortion(); - test_barrier_wait_abortion_unmatched(); - test_barrier_wait_abortion_local(); - test_barrier_wait_abortion_local_unmatched(); - test_barrier_exit(); - test_barrier_no_exit(); - test_barrier_pending_exit(); - - return 0; -} + if (v != VIRTUALIZATION_NONE) + return log_tests_skipped("This test requires a baremetal machine"); + }), + /* no outro */); From d19bff65ee52cc7caec113277c5ab233772690c1 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 12:41:42 +0100 Subject: [PATCH 5/6] test-namespace: Convert to TEST macro --- src/test/test-namespace.c | 71 ++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index dd66379b5c..8df5533d6e 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -14,7 +14,7 @@ #include "util.h" #include "virt.h" -static void test_namespace_cleanup_tmpdir(void) { +TEST(namespace_cleanup_tmpdir) { { _cleanup_(namespace_cleanup_tmpdirp) char *dir; assert_se(dir = strdup(RUN_SYSTEMD_EMPTY)); @@ -27,7 +27,7 @@ static void test_namespace_cleanup_tmpdir(void) { } } -static void test_tmpdir(const char *id, const char *A, const char *B) { +static void test_tmpdir_one(const char *id, const char *A, const char *B) { _cleanup_free_ char *a, *b; struct stat x, y; char *c, *d; @@ -63,6 +63,26 @@ static void test_tmpdir(const char *id, const char *A, const char *B) { } } +TEST(tmpdir) { + _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL; + sd_id128_t bid; + + assert_se(sd_id128_get_boot(&bid) >= 0); + + x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"); + y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"); + assert_se(x && y); + + test_tmpdir_one("abcd.service", x, y); + + z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); + zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); + + assert_se(z && zz); + + test_tmpdir_one("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz); +} + static void test_shareable_ns(unsigned long nsflag) { _cleanup_close_pair_ int s[2] = { -1, -1 }; pid_t pid1, pid2, pid3; @@ -121,15 +141,15 @@ static void test_shareable_ns(unsigned long nsflag) { assert_se(n == 1); } -static void test_netns(void) { +TEST(netns) { test_shareable_ns(CLONE_NEWNET); } -static void test_ipcns(void) { +TEST(ipcns) { test_shareable_ns(CLONE_NEWIPC); } -static void test_protect_kernel_logs(void) { +TEST(protect_kernel_logs) { int r; pid_t pid; static const NamespaceInfo ns_info = { @@ -200,37 +220,10 @@ static void test_protect_kernel_logs(void) { assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS); } -int main(int argc, char *argv[]) { - _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL; - sd_id128_t bid; - - test_setup_logging(LOG_INFO); - - test_namespace_cleanup_tmpdir(); - - if (!have_namespaces()) { - log_tests_skipped("Don't have namespace support"); - return EXIT_TEST_SKIP; - } - - assert_se(sd_id128_get_boot(&bid) >= 0); - - x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"); - y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"); - assert_se(x && y); - - test_tmpdir("abcd.service", x, y); - - z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); - zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); - - assert_se(z && zz); - - test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz); - - test_netns(); - test_ipcns(); - test_protect_kernel_logs(); - - return EXIT_SUCCESS; -} +DEFINE_CUSTOM_TEST_MAIN( + LOG_INFO, + ({ + if (!have_namespaces()) + return log_tests_skipped("Don't have namespace support"); + }), + /* no outro */); From 5a45a6bbb6e98a29b2815b5e59a24ffa11713dba Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 25 Nov 2021 12:48:41 +0100 Subject: [PATCH 6/6] test-parse-util: Add SI-suffix parse_size tests --- src/test/test-parse-util.c | 72 +++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c index 27f83f98ab..daa547c793 100644 --- a/src/test/test-parse-util.c +++ b/src/test/test-parse-util.c @@ -94,7 +94,7 @@ TEST(parse_mode) { assert_se(parse_mode(" 1", &m) >= 0 && m == 1); } -TEST(parse_size) { +TEST(parse_size_iec) { uint64_t bytes; assert_se(parse_size("", 1024, &bytes) == -EINVAL); @@ -164,6 +164,76 @@ TEST(parse_size) { assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); } +TEST(parse_size_si) { + uint64_t bytes; + + assert_se(parse_size("", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("111", 1000, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size("111.4", 1000, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size(" 112 B", 1000, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size(" 112.6 B", 1000, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size("3.5 K", 1000, &bytes) == 0); + assert_se(bytes == 3*1000 + 500); + + assert_se(parse_size("3. K", 1000, &bytes) == 0); + assert_se(bytes == 3*1000); + + assert_se(parse_size("3.0 K", 1000, &bytes) == 0); + assert_se(bytes == 3*1000); + + assert_se(parse_size("3. 0 K", 1000, &bytes) == -EINVAL); + + assert_se(parse_size(" 4 M 11.5K", 1000, &bytes) == 0); + assert_se(bytes == 4*1000*1000 + 11 * 1000 + 500); + + assert_se(parse_size("3B3.5G", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("3.5G3B", 1000, &bytes) == 0); + assert_se(bytes == 3ULL*1000*1000*1000 + 500*1000*1000 + 3); + + assert_se(parse_size("3.5G 4B", 1000, &bytes) == 0); + assert_se(bytes == 3ULL*1000*1000*1000 + 500*1000*1000 + 4); + + assert_se(parse_size("3B3G4T", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("4T3G3B", 1000, &bytes) == 0); + assert_se(bytes == (4ULL*1000 + 3)*1000*1000*1000 + 3); + + assert_se(parse_size(" 4 T 3 G 3 B", 1000, &bytes) == 0); + assert_se(bytes == (4ULL*1000 + 3)*1000*1000*1000 + 3); + + assert_se(parse_size("12P", 1000, &bytes) == 0); + assert_se(bytes == 12ULL * 1000*1000*1000*1000*1000); + + assert_se(parse_size("12P12P", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("3E 2P", 1000, &bytes) == 0); + assert_se(bytes == (3 * 1000 + 2ULL) * 1000*1000*1000*1000*1000); + + assert_se(parse_size("12X", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("12.5X", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("12.5e3", 1000, &bytes) == -EINVAL); + + assert_se(parse_size("1000E", 1000, &bytes) == -ERANGE); + assert_se(parse_size("-1", 1000, &bytes) == -ERANGE); + assert_se(parse_size("-1000E", 1000, &bytes) == -ERANGE); + + assert_se(parse_size("-1000P", 1000, &bytes) == -ERANGE); + + assert_se(parse_size("-10B 20K", 1000, &bytes) == -ERANGE); +} + TEST(parse_range) { unsigned lower, upper;