]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-util.c
build-sys: use #if Y instead of #ifdef Y everywhere
[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 static void test_container_of(void) {
108 struct mytype {
109 uint8_t pad1[3];
110 uint64_t v1;
111 uint8_t pad2[2];
112 uint32_t v2;
113 } _packed_ myval = { };
114
115 assert_cc(sizeof(myval) == 17);
116 assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
117 assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
118 assert_se(container_of(&container_of(&myval.v2,
119 struct mytype,
120 v2)->v1,
121 struct mytype,
122 v1) == &myval);
123 }
124
125 static void test_div_round_up(void) {
126 int div;
127
128 /* basic tests */
129 assert_se(DIV_ROUND_UP(0, 8) == 0);
130 assert_se(DIV_ROUND_UP(1, 8) == 1);
131 assert_se(DIV_ROUND_UP(8, 8) == 1);
132 assert_se(DIV_ROUND_UP(12, 8) == 2);
133 assert_se(DIV_ROUND_UP(16, 8) == 2);
134
135 /* test multiple evaluation */
136 div = 0;
137 assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
138 assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
139 assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
140 assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
141
142 /* overflow test with exact division */
143 assert_se(sizeof(0U) == 4);
144 assert_se(0xfffffffaU % 10U == 0U);
145 assert_se(0xfffffffaU / 10U == 429496729U);
146 assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
147 assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
148 assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
149
150 /* overflow test with rounded division */
151 assert_se(0xfffffffdU % 10U == 3U);
152 assert_se(0xfffffffdU / 10U == 429496729U);
153 assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
154 assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
155 assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
156 }
157
158 static void test_u64log2(void) {
159 assert_se(u64log2(0) == 0);
160 assert_se(u64log2(8) == 3);
161 assert_se(u64log2(9) == 3);
162 assert_se(u64log2(15) == 3);
163 assert_se(u64log2(16) == 4);
164 assert_se(u64log2(1024*1024) == 20);
165 assert_se(u64log2(1024*1024+5) == 20);
166 }
167
168 static void test_protect_errno(void) {
169 errno = 12;
170 {
171 PROTECT_ERRNO;
172 errno = 11;
173 }
174 assert_se(errno == 12);
175 }
176
177 static void test_in_set(void) {
178 assert_se(IN_SET(1, 1));
179 assert_se(IN_SET(1, 1, 2, 3, 4));
180 assert_se(IN_SET(2, 1, 2, 3, 4));
181 assert_se(IN_SET(3, 1, 2, 3, 4));
182 assert_se(IN_SET(4, 1, 2, 3, 4));
183 assert_se(!IN_SET(0, 1));
184 assert_se(!IN_SET(0, 1, 2, 3, 4));
185 }
186
187 static void test_log2i(void) {
188 assert_se(log2i(1) == 0);
189 assert_se(log2i(2) == 1);
190 assert_se(log2i(3) == 1);
191 assert_se(log2i(4) == 2);
192 assert_se(log2i(32) == 5);
193 assert_se(log2i(33) == 5);
194 assert_se(log2i(63) == 5);
195 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
196 }
197
198 static void test_raw_clone(void) {
199 pid_t parent, pid, pid2;
200
201 parent = getpid();
202 log_info("before clone: getpid()→"PID_FMT, parent);
203 assert_se(raw_getpid() == parent);
204
205 pid = raw_clone(0);
206 assert_se(pid >= 0);
207
208 pid2 = raw_getpid();
209 log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
210 pid, getpid(), pid2);
211 if (pid == 0) {
212 assert_se(pid2 != parent);
213 _exit(EXIT_SUCCESS);
214 } else {
215 int status;
216
217 assert_se(pid2 == parent);
218 waitpid(pid, &status, __WCLONE);
219 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
220 }
221 }
222
223 static void test_physical_memory(void) {
224 uint64_t p;
225 char buf[FORMAT_BYTES_MAX];
226
227 p = physical_memory();
228 assert_se(p > 0);
229 assert_se(p < UINT64_MAX);
230 assert_se(p % page_size() == 0);
231
232 log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p);
233 }
234
235 static void test_physical_memory_scale(void) {
236 uint64_t p;
237
238 p = physical_memory();
239
240 assert_se(physical_memory_scale(0, 100) == 0);
241 assert_se(physical_memory_scale(100, 100) == p);
242
243 log_info("Memory original: %" PRIu64, physical_memory());
244 log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100));
245 log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2);
246 log_info("Page size: %zu", page_size());
247
248 /* There might be an uneven number of pages, hence permit these calculations to be half a page off... */
249 assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size());
250 assert_se(physical_memory_scale(200, 100) == p*2);
251
252 assert_se(physical_memory_scale(0, 1) == 0);
253 assert_se(physical_memory_scale(1, 1) == p);
254 assert_se(physical_memory_scale(2, 1) == p*2);
255
256 assert_se(physical_memory_scale(0, 2) == 0);
257
258 assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size());
259 assert_se(physical_memory_scale(2, 2) == p);
260 assert_se(physical_memory_scale(4, 2) == p*2);
261
262 assert_se(physical_memory_scale(0, UINT32_MAX) == 0);
263 assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p);
264
265 /* overflow */
266 assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
267 }
268
269 static void test_system_tasks_max(void) {
270 uint64_t t;
271
272 t = system_tasks_max();
273 assert_se(t > 0);
274 assert_se(t < UINT64_MAX);
275
276 log_info("Max tasks: %" PRIu64, t);
277 }
278
279 static void test_system_tasks_max_scale(void) {
280 uint64_t t;
281
282 t = system_tasks_max();
283
284 assert_se(system_tasks_max_scale(0, 100) == 0);
285 assert_se(system_tasks_max_scale(100, 100) == t);
286
287 assert_se(system_tasks_max_scale(0, 1) == 0);
288 assert_se(system_tasks_max_scale(1, 1) == t);
289 assert_se(system_tasks_max_scale(2, 1) == 2*t);
290
291 assert_se(system_tasks_max_scale(0, 2) == 0);
292 assert_se(system_tasks_max_scale(1, 2) == t/2);
293 assert_se(system_tasks_max_scale(2, 2) == t);
294 assert_se(system_tasks_max_scale(3, 2) == (3*t)/2);
295 assert_se(system_tasks_max_scale(4, 2) == t*2);
296
297 assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0);
298 assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2);
299 assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t);
300
301 /* overflow */
302
303 assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
304 }
305
306 int main(int argc, char *argv[]) {
307 log_parse_environment();
308 log_open();
309
310 test_align_power2();
311 test_max();
312 test_container_of();
313 test_div_round_up();
314 test_u64log2();
315 test_protect_errno();
316 test_in_set();
317 test_log2i();
318 test_raw_clone();
319 test_physical_memory();
320 test_physical_memory_scale();
321 test_system_tasks_max();
322 test_system_tasks_max_scale();
323
324 return 0;
325 }