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