]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-file.c
logind: Don't match non-leader processes for utmp TTY determination (#38027)
[thirdparty/systemd.git] / src / test / test-unit-file.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
7d1e91d1 2
4f18ff2e
YW
3#include <unistd.h>
4
fa34123c 5#include "argv-util.h"
d8b34aae 6#include "fileio.h"
baa6a42d 7#include "initrd-util.h"
7d1e91d1 8#include "path-lookup.h"
d8b34aae
YW
9#include "path-util.h"
10#include "random-util.h"
11#include "rm-rf.h"
80276543 12#include "set.h"
da33cba0 13#include "special.h"
7d1e91d1
ZJS
14#include "strv.h"
15#include "tests.h"
fa34123c 16#include "time-util.h"
7d1e91d1
ZJS
17#include "unit-file.h"
18
4f7452a8 19TEST(unit_validate_alias_symlink_and_warn) {
cbfdbffb
ZJS
20 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a.service", "/other/b.service") == 0);
21 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a.service", "/other/b.socket") == -EXDEV);
22 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a.service", "/other/b.foobar") == -EXDEV);
23 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@.service", "/other/b@.service") == 0);
24 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@.service", "/other/b@.socket") == -EXDEV);
25 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV);
26 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV);
27 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@.service", "/other/b@YYY.service") == -EXDEV);
28 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@XXX.service", "/other/b@XXX.service") == 0);
29 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@XXX.service", "/other/b@.service") == 0);
30 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@.service", "/other/b.service") == -EXDEV);
31 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a.service", "/other/b@.service") == -EXDEV);
32 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a@.slice", "/other/b.slice") == -EINVAL);
33 assert_se(unit_validate_alias_symlink_or_warn(LOG_INFO, "/path/a.slice", "/other/b.slice") == -EINVAL);
7d1e91d1
ZJS
34}
35
4f7452a8 36TEST(unit_file_build_name_map) {
7dfc7139 37 _cleanup_(lookup_paths_done) LookupPaths lp = {};
e8630e69
ZJS
38 _cleanup_hashmap_free_ Hashmap *unit_ids = NULL;
39 _cleanup_hashmap_free_ Hashmap *unit_names = NULL;
e8630e69 40 const char *k, *dst;
4f7452a8 41 char **v, **ids;
91e0ee5f
ZJS
42 usec_t mtime = 0;
43 int r;
e8630e69 44
4f7452a8
JJ
45 ids = strv_skip(saved_argv, 1);
46
4870133b 47 assert_se(lookup_paths_init(&lp, RUNTIME_SCOPE_SYSTEM, 0, NULL) >= 0);
e8630e69 48
91e0ee5f 49 assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1);
e8630e69 50
90e74a66 51 HASHMAP_FOREACH_KEY(dst, k, unit_ids)
e8630e69
ZJS
52 log_info("ids: %s → %s", k, dst);
53
90e74a66 54 HASHMAP_FOREACH_KEY(v, k, unit_names) {
e8630e69
ZJS
55 _cleanup_free_ char *j = strv_join(v, ", ");
56 log_info("aliases: %s ← %s", k, j);
57 }
91e0ee5f
ZJS
58
59 char buf[FORMAT_TIMESTAMP_MAX];
60 log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime));
61
62 r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL);
63 assert_se(IN_SET(r, 0, 1));
64 if (r == 0)
65 log_debug("Cache rebuild skipped based on mtime.");
80276543 66
80276543
ZJS
67 STRV_FOREACH(id, ids) {
68 const char *fragment, *name;
5793a39d 69 _cleanup_set_free_ Set *names = NULL;
80276543
ZJS
70 log_info("*** %s ***", *id);
71 r = unit_file_find_fragment(unit_ids,
72 unit_names,
73 *id,
74 &fragment,
75 &names);
f21b863e 76 assert_se(r == 0);
80276543
ZJS
77 log_info("fragment: %s", fragment);
78 log_info("names:");
90e74a66 79 SET_FOREACH(name, names)
80276543
ZJS
80 log_info(" %s", name);
81 }
11e9347b
DDM
82
83 /* Make sure everything still works if we don't collect names. */
84 STRV_FOREACH(id, ids) {
85 const char *fragment;
86 log_info("*** %s ***", *id);
87 r = unit_file_find_fragment(unit_ids,
88 unit_names,
89 *id,
90 &fragment,
91 NULL);
92 assert_se(r == 0);
93 log_info("fragment: %s", fragment);
94 }
e8630e69
ZJS
95}
96
d8b34aae
YW
97static bool test_unit_file_remove_from_name_map_trail(const LookupPaths *lp, size_t trial) {
98 int r;
99
100 log_debug("/* %s(trial=%zu) */", __func__, trial);
101
102 _cleanup_hashmap_free_ Hashmap *unit_ids = NULL, *unit_names = NULL;
103 _cleanup_set_free_ Set *path_cache = NULL;
104 ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, NULL, &unit_ids, &unit_names, &path_cache));
105
106 _cleanup_free_ char *name = NULL;
107 for (size_t i = 0; i < 100; i++) {
108 ASSERT_OK(asprintf(&name, "test-unit-file-%"PRIx64".service", random_u64()));
109 if (!hashmap_contains(unit_ids, name))
110 break;
111 name = mfree(name);
112 }
113 ASSERT_NOT_NULL(name);
114
115 _cleanup_free_ char *path = path_join(lp->transient, name);
116 ASSERT_NOT_NULL(path);
117 ASSERT_OK(write_string_file(path, "[Unit]\n", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755));
118
119 uint64_t cache_timestamp_hash = 0;
120 ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, &cache_timestamp_hash, &unit_ids, &unit_names, &path_cache));
121
122 ASSERT_STREQ(hashmap_get(unit_ids, name), path);
123 ASSERT_TRUE(strv_equal(hashmap_get(unit_names, name), STRV_MAKE(name)));
124 ASSERT_TRUE(set_contains(path_cache, path));
125
126 ASSERT_OK_ERRNO(unlink(path));
127
d9000d70 128 ASSERT_OK(r = unit_file_remove_from_name_map(lp, &cache_timestamp_hash, &unit_ids, &unit_names, &path_cache, path));
d8b34aae
YW
129 if (r > 0)
130 return false; /* someone touches unit files. Retrying. */
131
132 ASSERT_FALSE(hashmap_contains(unit_ids, name));
133 ASSERT_FALSE(hashmap_contains(unit_names, path));
134 ASSERT_FALSE(set_contains(path_cache, path));
135
136 _cleanup_hashmap_free_ Hashmap *unit_ids_2 = NULL, *unit_names_2 = NULL;
137 _cleanup_set_free_ Set *path_cache_2 = NULL;
138 ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, NULL, &unit_ids_2, &unit_names_2, &path_cache_2));
139
140 if (hashmap_size(unit_ids) != hashmap_size(unit_ids_2) ||
141 hashmap_size(unit_names) != hashmap_size(unit_names_2) ||
142 !set_equal(path_cache, path_cache_2))
143 return false;
144
145 const char *k, *v;
146 HASHMAP_FOREACH_KEY(v, k, unit_ids)
147 if (!streq_ptr(hashmap_get(unit_ids_2, k), v))
148 return false;
149
150 char **l;
151 HASHMAP_FOREACH_KEY(l, k, unit_names)
152 if (!strv_equal_ignore_order(hashmap_get(unit_names_2, k), l))
153 return false;
154
155 return true;
156}
157
158
159TEST(unit_file_remove_from_name_map) {
160 _cleanup_(rm_rf_physical_and_freep) char *d = NULL;
161
162 _cleanup_(lookup_paths_done) LookupPaths lp = {};
163 ASSERT_OK(lookup_paths_init(&lp, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_TEMPORARY_GENERATED, NULL));
278e3adf 164 ASSERT_NOT_NULL((d = strdup(lp.temporary_dir)));
d8b34aae
YW
165
166 for (size_t i = 0; i < 10; i++)
167 if (test_unit_file_remove_from_name_map_trail(&lp, i))
168 return;
169
170 assert_not_reached();
171}
172
4f7452a8 173TEST(runlevel_to_target) {
da33cba0 174 in_initrd_force(false);
c79e88b3
IK
175 ASSERT_STREQ(runlevel_to_target(NULL), NULL);
176 ASSERT_STREQ(runlevel_to_target("unknown-runlevel"), NULL);
177 ASSERT_STREQ(runlevel_to_target("rd.unknown-runlevel"), NULL);
178 ASSERT_STREQ(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET);
179 ASSERT_STREQ(runlevel_to_target("rd.rescue"), NULL);
da33cba0
ZJS
180
181 in_initrd_force(true);
c79e88b3
IK
182 ASSERT_STREQ(runlevel_to_target(NULL), NULL);
183 ASSERT_STREQ(runlevel_to_target("unknown-runlevel"), NULL);
184 ASSERT_STREQ(runlevel_to_target("rd.unknown-runlevel"), NULL);
185 ASSERT_STREQ(runlevel_to_target("3"), NULL);
186 ASSERT_STREQ(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET);
da33cba0
ZJS
187}
188
99839c7e
LP
189static int intro(void) {
190 log_show_color(true);
191 return EXIT_SUCCESS;
192}
193
e85fdacc 194DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);