diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6abb4d6a5c..6aa59f6d09 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -104,7 +104,7 @@ jobs: --exclude "*.gperf" \ --output-file build/test/coverage/initial.coverage-info \ --base-directory src/ \ - --ignore-errors source,inconsistent \ + --ignore-errors source \ --no-external \ --substitute "s#src/src#src#g" diff --git a/src/test/test-path.c b/src/test/test-path.c index 52b9d75f60..ff1dee8474 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -18,46 +18,44 @@ static char *runtime_dir = NULL; -static int setup_test(Manager **m) { - char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", - "directorynotempty", "makedirectory"); - _cleanup_(manager_freep) Manager *tmp = NULL; +static int setup_test(Manager **ret) { int r; - ASSERT_NOT_NULL(m); - r = enter_cgroup_subroot(NULL); if (r == -ENOMEDIUM) return log_tests_skipped("cgroupfs not available"); - r = manager_new(RUNTIME_SCOPE_USER, MANAGER_TEST_RUN_BASIC, &tmp); + _cleanup_(manager_freep) Manager *m = NULL; + r = manager_new(RUNTIME_SCOPE_USER, MANAGER_TEST_RUN_BASIC, &m); if (manager_errno_skip_test(r)) return log_tests_skipped_errno(r, "manager_new"); ASSERT_OK(r); - ASSERT_OK(manager_startup(tmp, NULL, NULL, NULL, NULL)); + ASSERT_OK(manager_startup(m, NULL, NULL, NULL, NULL)); - STRV_FOREACH(test_path, tests_path) { - _cleanup_free_ char *p = NULL; - - p = strjoin("/tmp/test-path_", *test_path); - ASSERT_NOT_NULL(p); + FOREACH_STRING(s, + "exists", + "existsglobFOOBAR", + "changed", + "modified", + "unit", + "directorynotempty", + "makedirectory") { + _cleanup_free_ char *p = ASSERT_NOT_NULL(strjoin("/tmp/test-path_", s)); (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); } - *m = TAKE_PTR(tmp); + *ret = TAKE_PTR(m); return 0; } -static Service *service_for_path(Manager *m, Path *path, const char *service_name) { - _cleanup_free_ char *tmp = NULL; - Unit *service_unit = NULL; - +static Service* service_for_path(Manager *m, Path *path, const char *service_name) { ASSERT_NOT_NULL(m); ASSERT_NOT_NULL(path); + Unit *service_unit; if (!service_name) { - tmp = ASSERT_NOT_NULL(strreplace(UNIT(path)->id, ".path", ".service")); + _cleanup_free_ char *tmp = ASSERT_NOT_NULL(strreplace(UNIT(path)->id, ".path", ".service")); service_unit = manager_get_unit(m, tmp); } else service_unit = manager_get_unit(m, service_name); @@ -66,19 +64,6 @@ static Service *service_for_path(Manager *m, Path *path, const char *service_nam return SERVICE(service_unit); } -/* Define a test that gets a freshly-initialized Manager passed as `m`. The body returns 0 on - * success or EXIT_TEST_SKIP to skip; the wrapper hands the value back to the test framework. */ -#define PATH_TEST(name) \ - static int test_##name##_body(Manager *m); \ - TEST_RET(name) { \ - _cleanup_(manager_freep) Manager *m = NULL; \ - int r = setup_test(&m); \ - if (r != 0) \ - return r; \ - return test_##name##_body(m); \ - } \ - static int test_##name##_body(Manager *m) - static int _check_states( unsigned line, Manager *m, @@ -155,16 +140,20 @@ static int _check_states( return _r; \ } while (0) -PATH_TEST(path_exists) { +TEST_RET(path_exists) { const char *test_path = "/tmp/test-path_exists"; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, NULL); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, NULL); ASSERT_OK(unit_start(unit, NULL)); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); @@ -184,16 +173,20 @@ PATH_TEST(path_exists) { return 0; } -PATH_TEST(path_existsglob) { +TEST_RET(path_existsglob) { const char *test_path = "/tmp/test-path_existsglobFOOBAR"; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, NULL); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, NULL); ASSERT_OK(unit_start(unit, NULL)); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); @@ -213,17 +206,20 @@ PATH_TEST(path_existsglob) { return 0; } -PATH_TEST(path_changed) { +TEST_RET(path_changed) { const char *test_path = "/tmp/test-path_changed"; - FILE *f; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, NULL); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, NULL); ASSERT_OK(unit_start(unit, NULL)); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); @@ -235,8 +231,7 @@ PATH_TEST(path_changed) { ASSERT_OK(unit_stop(UNIT(service))); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); - f = ASSERT_NOT_NULL(fopen(test_path, "w")); - fclose(f); + fclose(ASSERT_NOT_NULL(fopen(test_path, "w"))); check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING); @@ -248,17 +243,20 @@ PATH_TEST(path_changed) { return 0; } -PATH_TEST(path_modified) { - _cleanup_fclose_ FILE *f = NULL; +TEST_RET(path_modified) { const char *test_path = "/tmp/test-path_modified"; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, NULL); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, NULL); ASSERT_OK(unit_start(unit, NULL)); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); @@ -270,7 +268,7 @@ PATH_TEST(path_modified) { ASSERT_OK(unit_stop(UNIT(service))); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); - f = ASSERT_NOT_NULL(fopen(test_path, "w")); + _cleanup_fclose_ FILE *f = ASSERT_NOT_NULL(fopen(test_path, "w")); fputs("test", f); check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING); @@ -283,16 +281,20 @@ PATH_TEST(path_modified) { return 0; } -PATH_TEST(path_unit) { +TEST_RET(path_unit) { const char *test_path = "/tmp/test-path_unit"; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, "path-mycustomunit.service"); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, "path-mycustomunit.service"); ASSERT_OK(unit_start(unit, NULL)); check_states(m, path, service, PATH_WAITING, SERVICE_DEAD); @@ -308,16 +310,20 @@ PATH_TEST(path_unit) { return 0; } -PATH_TEST(path_directorynotempty) { +TEST_RET(path_directorynotempty) { const char *test_file, *test_path = "/tmp/test-path_directorynotempty/"; - Unit *unit = NULL; - Path *path = NULL; - Service *service = NULL; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit)); - path = PATH(unit); - service = service_for_path(m, path, NULL); + Path *path = PATH(unit); + Service *service = service_for_path(m, path, NULL); ASSERT_FAIL(access(test_path, F_OK)); @@ -344,11 +350,16 @@ PATH_TEST(path_directorynotempty) { return 0; } -PATH_TEST(path_makedirectory_directorymode) { +TEST_RET(path_makedirectory_directorymode) { const char *test_path = "/tmp/test-path_makedirectory/"; - Unit *unit = NULL; - struct stat s; + int r; + _cleanup_(manager_freep) Manager *m = NULL; + r = setup_test(&m); + if (r != 0) + return r; + + Unit *unit; ASSERT_OK(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit)); ASSERT_FAIL(access(test_path, F_OK)); @@ -359,6 +370,7 @@ PATH_TEST(path_makedirectory_directorymode) { ASSERT_OK_ERRNO(access(test_path, F_OK)); /* Check the mode we specified with DirectoryMode=0744 */ + struct stat s; ASSERT_OK_ERRNO(stat(test_path, &s)); ASSERT_EQ((mode_t) (s.st_mode & S_IRWXU), (mode_t) 0700); ASSERT_EQ((mode_t) (s.st_mode & S_IRWXG), (mode_t) 0040); diff --git a/src/test/test-qmp-client.c b/src/test/test-qmp-client.c index 948122720e..9c56df29bc 100644 --- a/src/test/test-qmp-client.c +++ b/src/test/test-qmp-client.c @@ -151,20 +151,6 @@ static void run_qmp_test(sd_fiber_func_t mock_fn, sd_fiber_func_t client_fn) { ASSERT_OK(sd_future_result(mock_f)); } -/* Define a test whose body runs as the client fiber on an event loop shared with `mock_fn`. - * The body receives `QmpClient *client` as its argument. */ -#define QMP_TEST(name, mock_fn) \ - static int test_##name##_body(QmpClient *client); \ - static int test_##name##_fiber(void *userdata) { \ - int r = test_##name##_body(userdata); \ - ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); \ - return r; \ - } \ - TEST(name) { \ - run_qmp_test(mock_fn, test_##name##_fiber); \ - } \ - static int test_##name##_body(QmpClient *client) - static int mock_qmp_basic_fiber(void *userdata) { _cleanup_(json_stream_done) JsonStream s = {}; _cleanup_(sd_json_variant_unrefp) sd_json_variant *stop_event = NULL; @@ -201,7 +187,8 @@ static int test_event_callback( return 0; } -QMP_TEST(qmp_client_basic, mock_qmp_basic_fiber) { +static int qmp_client_basic_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL; _cleanup_free_ char *error_desc = NULL; bool event_received = false; @@ -220,9 +207,14 @@ QMP_TEST(qmp_client_basic, mock_qmp_basic_fiber) { ASSERT_OK_POSITIVE(qmp_client_call(client, "cont", NULL, NULL, NULL)); ASSERT_TRUE(event_received); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_basic) { + run_qmp_test(mock_qmp_basic_fiber, qmp_client_basic_fiber); +} + static int mock_qmp_eof_fiber(void *userdata) { _cleanup_(json_stream_done) JsonStream s = {}; @@ -232,12 +224,18 @@ static int mock_qmp_eof_fiber(void *userdata) { return 0; } -QMP_TEST(qmp_client_eof, mock_qmp_eof_fiber) { +static int qmp_client_eof_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); int r = qmp_client_call(client, "query-status", NULL, NULL, NULL); ASSERT_TRUE(ERRNO_IS_NEG_DISCONNECT(r)); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_eof) { + run_qmp_test(mock_qmp_eof_fiber, qmp_client_eof_fiber); +} + static int mock_qmp_call_fiber(void *userdata) { _cleanup_(json_stream_done) JsonStream s = {}; @@ -250,7 +248,8 @@ static int mock_qmp_call_fiber(void *userdata) { return 0; } -QMP_TEST(qmp_client_call, mock_qmp_call_fiber) { +static int qmp_client_call_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); _cleanup_(sd_future_cancel_wait_unrefp) sd_future *f = NULL; _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL; _cleanup_free_ char *error_desc = NULL; @@ -286,9 +285,14 @@ QMP_TEST(qmp_client_call, mock_qmp_call_fiber) { /* qmp_client_call() also surfaces QMP errors as -EIO, regardless of whether the caller * passed ret_error_desc. */ ASSERT_ERROR(qmp_client_call(client, "stop", NULL, NULL, NULL), EIO); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_call) { + run_qmp_test(mock_qmp_call_fiber, qmp_client_call_fiber); +} + static int mock_qmp_call_disconnect_fiber(void *userdata) { _cleanup_(json_stream_done) JsonStream s = {}; _cleanup_(sd_json_variant_unrefp) sd_json_variant *stop_cmd = NULL; @@ -302,12 +306,18 @@ static int mock_qmp_call_disconnect_fiber(void *userdata) { return 0; } -QMP_TEST(qmp_client_call_disconnect, mock_qmp_call_disconnect_fiber) { +static int qmp_client_call_disconnect_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); int r = qmp_client_call(client, "stop", NULL, NULL, NULL); ASSERT_TRUE(ERRNO_IS_NEG_DISCONNECT(r)); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_call_disconnect) { + run_qmp_test(mock_qmp_call_disconnect_fiber, qmp_client_call_disconnect_fiber); +} + static int mock_qmp_fd_fiber(void *userdata) { _cleanup_(json_stream_done) JsonStream s = {}; _cleanup_(sd_json_variant_unrefp) sd_json_variant *cap_cmd = NULL, *addfd_cmd = NULL, @@ -336,7 +346,8 @@ static int mock_qmp_fd_fiber(void *userdata) { return 0; } -QMP_TEST(qmp_client_invoke_with_fd, mock_qmp_fd_fiber) { +static int qmp_client_invoke_with_fd_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); _cleanup_(sd_json_variant_unrefp) sd_json_variant *args = NULL; _cleanup_close_ int fd_to_pass = -EBADF; _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL; @@ -349,9 +360,14 @@ QMP_TEST(qmp_client_invoke_with_fd, mock_qmp_fd_fiber) { QMP_CLIENT_ARGS_FD(args, TAKE_FD(fd_to_pass)), &result, NULL)); ASSERT_NOT_NULL(result); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_invoke_with_fd) { + run_qmp_test(mock_qmp_fd_fiber, qmp_client_invoke_with_fd_fiber); +} + static int on_dead_peer_reply( QmpClient *client, sd_json_variant *result, @@ -433,7 +449,8 @@ static int tripwire_callback( return 0; } -QMP_TEST(qmp_client_invoke_slot_lifecycle, mock_qmp_slot_fiber) { +static int qmp_client_invoke_slot_lifecycle_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); _cleanup_(qmp_slot_unrefp) QmpSlot *slot = NULL; ASSERT_OK(qmp_client_invoke(client, &slot, "query-status", NULL, nop_callback, NULL)); @@ -447,10 +464,16 @@ QMP_TEST(qmp_client_invoke_slot_lifecycle, mock_qmp_slot_fiber) { /* Explicit out-of-order unref exercises the already-disconnected path in qmp_slot_free(). */ slot = qmp_slot_unref(slot); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } -QMP_TEST(qmp_client_invoke_slot_cancel, mock_qmp_slot_fiber) { +TEST(qmp_invoke_slot_lifecycle) { + run_qmp_test(mock_qmp_slot_fiber, qmp_client_invoke_slot_lifecycle_fiber); +} + +static int qmp_client_invoke_slot_cancel_fiber(void *userdata) { + QmpClient *client = ASSERT_NOT_NULL(userdata); QmpSlot *slot = NULL; bool fired = false; @@ -463,9 +486,14 @@ QMP_TEST(qmp_client_invoke_slot_cancel, mock_qmp_slot_fiber) { ASSERT_OK_POSITIVE(qmp_client_call(client, "stop", NULL, NULL, NULL)); ASSERT_FALSE(fired); + ASSERT_OK(sd_event_exit(sd_fiber_get_event(), 0)); return 0; } +TEST(qmp_invoke_slot_cancel) { + run_qmp_test(mock_qmp_slot_fiber, qmp_client_invoke_slot_cancel_fiber); +} + TEST(qmp_schema_has_member) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *schema = NULL;