chiark / gitweb /
Prep v236 : Add missing SPDX-License-Identifier (8/9) src/test
[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 "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 #if 0 /// UNNEEDED by elogind
207 static void test_raw_clone(void) {
208         pid_t parent, pid, pid2;
209
210         parent = getpid();
211         log_info("before clone: getpid()→"PID_FMT, parent);
212         assert_se(raw_getpid() == parent);
213
214         pid = raw_clone(0);
215         assert_se(pid >= 0);
216
217         pid2 = raw_getpid();
218         log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
219                  pid, getpid(), pid2);
220         if (pid == 0) {
221                 assert_se(pid2 != parent);
222                 _exit(EXIT_SUCCESS);
223         } else {
224                 int status;
225
226                 assert_se(pid2 == parent);
227                 waitpid(pid, &status, __WCLONE);
228                 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
229         }
230 }
231 #endif // 0
232
233 static void test_physical_memory(void) {
234         uint64_t p;
235         char buf[FORMAT_BYTES_MAX];
236
237         p = physical_memory();
238         assert_se(p > 0);
239         assert_se(p < UINT64_MAX);
240         assert_se(p % page_size() == 0);
241
242         log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p);
243 }
244
245 static void test_physical_memory_scale(void) {
246         uint64_t p;
247
248         p = physical_memory();
249
250         assert_se(physical_memory_scale(0, 100) == 0);
251         assert_se(physical_memory_scale(100, 100) == p);
252
253         log_info("Memory original: %" PRIu64, physical_memory());
254         log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100));
255         log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2);
256         log_info("Page size: %zu", page_size());
257
258         /* There might be an uneven number of pages, hence permit these calculations to be half a page off... */
259         assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size());
260         assert_se(physical_memory_scale(200, 100) == p*2);
261
262         assert_se(physical_memory_scale(0, 1) == 0);
263         assert_se(physical_memory_scale(1, 1) == p);
264         assert_se(physical_memory_scale(2, 1) == p*2);
265
266         assert_se(physical_memory_scale(0, 2) == 0);
267
268         assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size());
269         assert_se(physical_memory_scale(2, 2) == p);
270         assert_se(physical_memory_scale(4, 2) == p*2);
271
272         assert_se(physical_memory_scale(0, UINT32_MAX) == 0);
273         assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p);
274
275         /* overflow */
276         assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
277 }
278
279 static void test_system_tasks_max(void) {
280         uint64_t t;
281
282         t = system_tasks_max();
283         assert_se(t > 0);
284         assert_se(t < UINT64_MAX);
285
286         log_info("Max tasks: %" PRIu64, t);
287 }
288
289 static void test_system_tasks_max_scale(void) {
290         uint64_t t;
291
292         t = system_tasks_max();
293
294         assert_se(system_tasks_max_scale(0, 100) == 0);
295         assert_se(system_tasks_max_scale(100, 100) == t);
296
297         assert_se(system_tasks_max_scale(0, 1) == 0);
298         assert_se(system_tasks_max_scale(1, 1) == t);
299         assert_se(system_tasks_max_scale(2, 1) == 2*t);
300
301         assert_se(system_tasks_max_scale(0, 2) == 0);
302         assert_se(system_tasks_max_scale(1, 2) == t/2);
303         assert_se(system_tasks_max_scale(2, 2) == t);
304         assert_se(system_tasks_max_scale(3, 2) == (3*t)/2);
305         assert_se(system_tasks_max_scale(4, 2) == t*2);
306
307         assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0);
308         assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2);
309         assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t);
310
311         /* overflow */
312
313         assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
314 }
315
316 int main(int argc, char *argv[]) {
317         log_parse_environment();
318         log_open();
319
320         test_align_power2();
321         test_max();
322         test_container_of();
323         test_div_round_up();
324         test_u64log2();
325         test_protect_errno();
326         test_in_set();
327         test_log2i();
328 #if 0 /// UNNEEDED by elogind
329         test_raw_clone();
330 #endif // 0
331         test_physical_memory();
332         test_physical_memory_scale();
333         test_system_tasks_max();
334         test_system_tasks_max_scale();
335
336         return 0;
337 }