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