]>
Commit | Line | Data |
---|---|---|
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 | 19 | TEST(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 | 36 | TEST(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 |
97 | static 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 | ||
159 | TEST(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 | 173 | TEST(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 |
189 | static int intro(void) { |
190 | log_show_color(true); | |
191 | return EXIT_SUCCESS; | |
192 | } | |
193 | ||
e85fdacc | 194 | DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro); |