]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-util.c
Merge pull request #7388 from keszybz/doc-tweak
[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 "parse-util.h"
30 #include "raw-clone.h"
31 #include "rm-rf.h"
32 #include "string-util.h"
33 #include "util.h"
34
35 static void test_align_power2(void) {
36 unsigned long i, p2;
37
38 assert_se(ALIGN_POWER2(0) == 0);
39 assert_se(ALIGN_POWER2(1) == 1);
40 assert_se(ALIGN_POWER2(2) == 2);
41 assert_se(ALIGN_POWER2(3) == 4);
42 assert_se(ALIGN_POWER2(12) == 16);
43
44 assert_se(ALIGN_POWER2(ULONG_MAX) == 0);
45 assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0);
46 assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0);
47 assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1);
48 assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0);
49
50 for (i = 1; i < 131071; ++i) {
51 for (p2 = 1; p2 < i; p2 <<= 1)
52 /* empty */ ;
53
54 assert_se(ALIGN_POWER2(i) == p2);
55 }
56
57 for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) {
58 for (p2 = 1; p2 && p2 < i; p2 <<= 1)
59 /* empty */ ;
60
61 assert_se(ALIGN_POWER2(i) == p2);
62 }
63 }
64
65 static void test_max(void) {
66 static const struct {
67 int a;
68 int b[CONST_MAX(10, 100)];
69 } val1 = {
70 .a = CONST_MAX(10, 100),
71 };
72 int d = 0;
73
74 assert_cc(sizeof(val1.b) == sizeof(int) * 100);
75
76 /* CONST_MAX returns (void) instead of a value if the passed arguments
77 * are not of the same type or not constant expressions. */
78 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
79 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
80
81 assert_se(val1.a == 100);
82 assert_se(MAX(++d, 0) == 1);
83 assert_se(d == 1);
84
85 assert_cc(MAXSIZE(char[3], uint16_t) == 3);
86 assert_cc(MAXSIZE(char[3], uint32_t) == 4);
87 assert_cc(MAXSIZE(char, long) == sizeof(long));
88
89 assert_se(MAX(-5, 5) == 5);
90 assert_se(MAX(5, 5) == 5);
91 assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5);
92 assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3);
93 assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5);
94 assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2);
95 assert_se(LESS_BY(8, 4) == 4);
96 assert_se(LESS_BY(8, 8) == 0);
97 assert_se(LESS_BY(4, 8) == 0);
98 assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
99 assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
100 assert_se(CLAMP(-5, 0, 1) == 0);
101 assert_se(CLAMP(5, 0, 1) == 1);
102 assert_se(CLAMP(5, -10, 1) == 1);
103 assert_se(CLAMP(5, -10, 10) == 5);
104 assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
105 }
106
107 #pragma GCC diagnostic push
108 #ifdef __clang__
109 # pragma GCC diagnostic ignored "-Waddress-of-packed-member"
110 #endif
111
112 static void test_container_of(void) {
113 struct mytype {
114 uint8_t pad1[3];
115 uint64_t v1;
116 uint8_t pad2[2];
117 uint32_t v2;
118 } _packed_ myval = { };
119
120 assert_cc(sizeof(myval) == 17);
121 assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
122 assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
123 assert_se(container_of(&container_of(&myval.v2,
124 struct mytype,
125 v2)->v1,
126 struct mytype,
127 v1) == &myval);
128 }
129
130 #pragma GCC diagnostic pop
131
132 static void test_div_round_up(void) {
133 int div;
134
135 /* basic tests */
136 assert_se(DIV_ROUND_UP(0, 8) == 0);
137 assert_se(DIV_ROUND_UP(1, 8) == 1);
138 assert_se(DIV_ROUND_UP(8, 8) == 1);
139 assert_se(DIV_ROUND_UP(12, 8) == 2);
140 assert_se(DIV_ROUND_UP(16, 8) == 2);
141
142 /* test multiple evaluation */
143 div = 0;
144 assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
145 assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
146 assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
147 assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
148
149 /* overflow test with exact division */
150 assert_se(sizeof(0U) == 4);
151 assert_se(0xfffffffaU % 10U == 0U);
152 assert_se(0xfffffffaU / 10U == 429496729U);
153 assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
154 assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
155 assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
156
157 /* overflow test with rounded division */
158 assert_se(0xfffffffdU % 10U == 3U);
159 assert_se(0xfffffffdU / 10U == 429496729U);
160 assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
161 assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
162 assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
163 }
164
165 static void test_u64log2(void) {
166 assert_se(u64log2(0) == 0);
167 assert_se(u64log2(8) == 3);
168 assert_se(u64log2(9) == 3);
169 assert_se(u64log2(15) == 3);
170 assert_se(u64log2(16) == 4);
171 assert_se(u64log2(1024*1024) == 20);
172 assert_se(u64log2(1024*1024+5) == 20);
173 }
174
175 static void test_protect_errno(void) {
176 errno = 12;
177 {
178 PROTECT_ERRNO;
179 errno = 11;
180 }
181 assert_se(errno == 12);
182 }
183
184 static void test_in_set(void) {
185 assert_se(IN_SET(1, 1));
186 assert_se(IN_SET(1, 1, 2, 3, 4));
187 assert_se(IN_SET(2, 1, 2, 3, 4));
188 assert_se(IN_SET(3, 1, 2, 3, 4));
189 assert_se(IN_SET(4, 1, 2, 3, 4));
190 assert_se(!IN_SET(0, 1));
191 assert_se(!IN_SET(0, 1, 2, 3, 4));
192 }
193
194 static void test_log2i(void) {
195 assert_se(log2i(1) == 0);
196 assert_se(log2i(2) == 1);
197 assert_se(log2i(3) == 1);
198 assert_se(log2i(4) == 2);
199 assert_se(log2i(32) == 5);
200 assert_se(log2i(33) == 5);
201 assert_se(log2i(63) == 5);
202 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
203 }
204
205 static void test_raw_clone(void) {
206 pid_t parent, pid, pid2;
207
208 parent = getpid();
209 log_info("before clone: getpid()→"PID_FMT, parent);
210 assert_se(raw_getpid() == parent);
211
212 pid = raw_clone(0);
213 assert_se(pid >= 0);
214
215 pid2 = raw_getpid();
216 log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
217 pid, getpid(), pid2);
218 if (pid == 0) {
219 assert_se(pid2 != parent);
220 _exit(EXIT_SUCCESS);
221 } else {
222 int status;
223
224 assert_se(pid2 == parent);
225 waitpid(pid, &status, __WCLONE);
226 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
227 }
228 }
229
230 static void test_physical_memory(void) {
231 uint64_t p;
232 char buf[FORMAT_BYTES_MAX];
233
234 p = physical_memory();
235 assert_se(p > 0);
236 assert_se(p < UINT64_MAX);
237 assert_se(p % page_size() == 0);
238
239 log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p);
240 }
241
242 static void test_physical_memory_scale(void) {
243 uint64_t p;
244
245 p = physical_memory();
246
247 assert_se(physical_memory_scale(0, 100) == 0);
248 assert_se(physical_memory_scale(100, 100) == p);
249
250 log_info("Memory original: %" PRIu64, physical_memory());
251 log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100));
252 log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2);
253 log_info("Page size: %zu", page_size());
254
255 /* There might be an uneven number of pages, hence permit these calculations to be half a page off... */
256 assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size());
257 assert_se(physical_memory_scale(200, 100) == p*2);
258
259 assert_se(physical_memory_scale(0, 1) == 0);
260 assert_se(physical_memory_scale(1, 1) == p);
261 assert_se(physical_memory_scale(2, 1) == p*2);
262
263 assert_se(physical_memory_scale(0, 2) == 0);
264
265 assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size());
266 assert_se(physical_memory_scale(2, 2) == p);
267 assert_se(physical_memory_scale(4, 2) == p*2);
268
269 assert_se(physical_memory_scale(0, UINT32_MAX) == 0);
270 assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p);
271
272 /* overflow */
273 assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
274 }
275
276 static void test_system_tasks_max(void) {
277 uint64_t t;
278
279 t = system_tasks_max();
280 assert_se(t > 0);
281 assert_se(t < UINT64_MAX);
282
283 log_info("Max tasks: %" PRIu64, t);
284 }
285
286 static void test_system_tasks_max_scale(void) {
287 uint64_t t;
288
289 t = system_tasks_max();
290
291 assert_se(system_tasks_max_scale(0, 100) == 0);
292 assert_se(system_tasks_max_scale(100, 100) == t);
293
294 assert_se(system_tasks_max_scale(0, 1) == 0);
295 assert_se(system_tasks_max_scale(1, 1) == t);
296 assert_se(system_tasks_max_scale(2, 1) == 2*t);
297
298 assert_se(system_tasks_max_scale(0, 2) == 0);
299 assert_se(system_tasks_max_scale(1, 2) == t/2);
300 assert_se(system_tasks_max_scale(2, 2) == t);
301 assert_se(system_tasks_max_scale(3, 2) == (3*t)/2);
302 assert_se(system_tasks_max_scale(4, 2) == t*2);
303
304 assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0);
305 assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2);
306 assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t);
307
308 /* overflow */
309
310 assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
311 }
312
313 int main(int argc, char *argv[]) {
314 log_parse_environment();
315 log_open();
316
317 test_align_power2();
318 test_max();
319 test_container_of();
320 test_div_round_up();
321 test_u64log2();
322 test_protect_errno();
323 test_in_set();
324 test_log2i();
325 test_raw_clone();
326 test_physical_memory();
327 test_physical_memory_scale();
328 test_system_tasks_max();
329 test_system_tasks_max_scale();
330
331 return 0;
332 }