]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-util.c
Merge pull request #2794 from jhol/dont-unmount-initramfs-mounts
[thirdparty/systemd.git] / src / test / test-util.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25
26 #include "def.h"
27 #include "fileio.h"
28 #include "fs-util.h"
29 #include "rm-rf.h"
30 #include "string-util.h"
31 #include "util.h"
32
33 static void test_align_power2(void) {
34 unsigned long i, p2;
35
36 assert_se(ALIGN_POWER2(0) == 0);
37 assert_se(ALIGN_POWER2(1) == 1);
38 assert_se(ALIGN_POWER2(2) == 2);
39 assert_se(ALIGN_POWER2(3) == 4);
40 assert_se(ALIGN_POWER2(12) == 16);
41
42 assert_se(ALIGN_POWER2(ULONG_MAX) == 0);
43 assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0);
44 assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0);
45 assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1);
46 assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0);
47
48 for (i = 1; i < 131071; ++i) {
49 for (p2 = 1; p2 < i; p2 <<= 1)
50 /* empty */ ;
51
52 assert_se(ALIGN_POWER2(i) == p2);
53 }
54
55 for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) {
56 for (p2 = 1; p2 && p2 < i; p2 <<= 1)
57 /* empty */ ;
58
59 assert_se(ALIGN_POWER2(i) == p2);
60 }
61 }
62
63 static void test_max(void) {
64 static const struct {
65 int a;
66 int b[CONST_MAX(10, 100)];
67 } val1 = {
68 .a = CONST_MAX(10, 100),
69 };
70 int d = 0;
71
72 assert_cc(sizeof(val1.b) == sizeof(int) * 100);
73
74 /* CONST_MAX returns (void) instead of a value if the passed arguments
75 * are not of the same type or not constant expressions. */
76 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
77 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
78
79 assert_se(val1.a == 100);
80 assert_se(MAX(++d, 0) == 1);
81 assert_se(d == 1);
82
83 assert_cc(MAXSIZE(char[3], uint16_t) == 3);
84 assert_cc(MAXSIZE(char[3], uint32_t) == 4);
85 assert_cc(MAXSIZE(char, long) == sizeof(long));
86
87 assert_se(MAX(-5, 5) == 5);
88 assert_se(MAX(5, 5) == 5);
89 assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5);
90 assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3);
91 assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5);
92 assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2);
93 assert_se(LESS_BY(8, 4) == 4);
94 assert_se(LESS_BY(8, 8) == 0);
95 assert_se(LESS_BY(4, 8) == 0);
96 assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
97 assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
98 assert_se(CLAMP(-5, 0, 1) == 0);
99 assert_se(CLAMP(5, 0, 1) == 1);
100 assert_se(CLAMP(5, -10, 1) == 1);
101 assert_se(CLAMP(5, -10, 10) == 5);
102 assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
103 }
104
105 static void test_container_of(void) {
106 struct mytype {
107 uint8_t pad1[3];
108 uint64_t v1;
109 uint8_t pad2[2];
110 uint32_t v2;
111 } _packed_ myval = { };
112
113 assert_cc(sizeof(myval) == 17);
114 assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
115 assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
116 assert_se(container_of(&container_of(&myval.v2,
117 struct mytype,
118 v2)->v1,
119 struct mytype,
120 v1) == &myval);
121 }
122
123 static void test_div_round_up(void) {
124 int div;
125
126 /* basic tests */
127 assert_se(DIV_ROUND_UP(0, 8) == 0);
128 assert_se(DIV_ROUND_UP(1, 8) == 1);
129 assert_se(DIV_ROUND_UP(8, 8) == 1);
130 assert_se(DIV_ROUND_UP(12, 8) == 2);
131 assert_se(DIV_ROUND_UP(16, 8) == 2);
132
133 /* test multiple evaluation */
134 div = 0;
135 assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
136 assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
137 assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
138 assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
139
140 /* overflow test with exact division */
141 assert_se(sizeof(0U) == 4);
142 assert_se(0xfffffffaU % 10U == 0U);
143 assert_se(0xfffffffaU / 10U == 429496729U);
144 assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
145 assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
146 assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
147
148 /* overflow test with rounded division */
149 assert_se(0xfffffffdU % 10U == 3U);
150 assert_se(0xfffffffdU / 10U == 429496729U);
151 assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
152 assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
153 assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
154 }
155
156 static void test_u64log2(void) {
157 assert_se(u64log2(0) == 0);
158 assert_se(u64log2(8) == 3);
159 assert_se(u64log2(9) == 3);
160 assert_se(u64log2(15) == 3);
161 assert_se(u64log2(16) == 4);
162 assert_se(u64log2(1024*1024) == 20);
163 assert_se(u64log2(1024*1024+5) == 20);
164 }
165
166 static void test_protect_errno(void) {
167 errno = 12;
168 {
169 PROTECT_ERRNO;
170 errno = 11;
171 }
172 assert_se(errno == 12);
173 }
174
175 static void test_in_set(void) {
176 assert_se(IN_SET(1, 1));
177 assert_se(IN_SET(1, 1, 2, 3, 4));
178 assert_se(IN_SET(2, 1, 2, 3, 4));
179 assert_se(IN_SET(3, 1, 2, 3, 4));
180 assert_se(IN_SET(4, 1, 2, 3, 4));
181 assert_se(!IN_SET(0, 1));
182 assert_se(!IN_SET(0, 1, 2, 3, 4));
183 }
184
185 static void test_log2i(void) {
186 assert_se(log2i(1) == 0);
187 assert_se(log2i(2) == 1);
188 assert_se(log2i(3) == 1);
189 assert_se(log2i(4) == 2);
190 assert_se(log2i(32) == 5);
191 assert_se(log2i(33) == 5);
192 assert_se(log2i(63) == 5);
193 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
194 }
195
196 static void test_execute_directory(void) {
197 char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
198 char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
199 const char * dirs[] = {template_hi, template_lo, NULL};
200 const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
201
202 assert_se(mkdtemp(template_lo));
203 assert_se(mkdtemp(template_hi));
204
205 name = strjoina(template_lo, "/script");
206 name2 = strjoina(template_hi, "/script2");
207 name3 = strjoina(template_lo, "/useless");
208 overridden = strjoina(template_lo, "/overridden");
209 override = strjoina(template_hi, "/overridden");
210 masked = strjoina(template_lo, "/masked");
211 mask = strjoina(template_hi, "/masked");
212
213 assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
214 assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
215 assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
216 assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
217 assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
218 assert_se(symlink("/dev/null", mask) == 0);
219 assert_se(chmod(name, 0755) == 0);
220 assert_se(chmod(name2, 0755) == 0);
221 assert_se(chmod(overridden, 0755) == 0);
222 assert_se(chmod(override, 0755) == 0);
223 assert_se(chmod(masked, 0755) == 0);
224 assert_se(touch(name3) >= 0);
225
226 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
227
228 assert_se(chdir(template_lo) == 0);
229 assert_se(access("it_works", F_OK) >= 0);
230 assert_se(access("failed", F_OK) < 0);
231
232 assert_se(chdir(template_hi) == 0);
233 assert_se(access("it_works2", F_OK) >= 0);
234 assert_se(access("failed", F_OK) < 0);
235
236 (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
237 (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
238 }
239
240 static void test_raw_clone(void) {
241 pid_t parent, pid, pid2;
242
243 parent = getpid();
244 log_info("before clone: getpid()→"PID_FMT, parent);
245 assert_se(raw_getpid() == parent);
246
247 pid = raw_clone(0, NULL);
248 assert_se(pid >= 0);
249
250 pid2 = raw_getpid();
251 log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
252 pid, getpid(), pid2);
253 if (pid == 0) {
254 assert_se(pid2 != parent);
255 _exit(EXIT_SUCCESS);
256 } else {
257 int status;
258
259 assert_se(pid2 == parent);
260 waitpid(pid, &status, __WCLONE);
261 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
262 }
263 }
264
265 int main(int argc, char *argv[]) {
266 log_parse_environment();
267 log_open();
268
269 test_align_power2();
270 test_max();
271 test_container_of();
272 test_div_round_up();
273 test_u64log2();
274 test_protect_errno();
275 test_in_set();
276 test_log2i();
277 test_execute_directory();
278 test_raw_clone();
279
280 return 0;
281 }