dte test coverage


Directory: ./
File: test/util.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 2467 2468 99.9%
Functions: 100 100 100.0%
Branches: 81 82 98.8%

Line Branch Exec Source
1 #include <ctype.h>
2 #include <fcntl.h>
3 #include <limits.h>
4 #include <locale.h>
5 #include <signal.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include "test.h"
11 #include "util/arith.h"
12 #include "util/ascii.h"
13 #include "util/base64.h"
14 #include "util/bit.h"
15 #include "util/fd.h"
16 #include "util/fork-exec.h"
17 #include "util/hash.h"
18 #include "util/hashmap.h"
19 #include "util/hashset.h"
20 #include "util/intern.h"
21 #include "util/intmap.h"
22 #include "util/list.h"
23 #include "util/log.h"
24 #include "util/numtostr.h"
25 #include "util/path.h"
26 #include "util/progname.h"
27 #include "util/ptr-array.h"
28 #include "util/readfile.h"
29 #include "util/str-util.h"
30 #include "util/string-view.h"
31 #include "util/string.h"
32 #include "util/strtonum.h"
33 #include "util/time-util.h"
34 #include "util/unicode.h"
35 #include "util/utf8.h"
36 #include "util/xmalloc.h"
37 #include "util/xmemmem.h"
38 #include "util/xmemrchr.h"
39 #include "util/xreadwrite.h"
40 #include "util/xsnprintf.h"
41 #include "util/xstdio.h"
42
43 1 static void test_util_macros(TestContext *ctx)
44 {
45 1 EXPECT_EQ(STRLEN(""), 0);
46 1 EXPECT_EQ(STRLEN("a"), 1);
47 1 EXPECT_EQ(STRLEN("123456789"), 9);
48
49 1 EXPECT_EQ(ARRAYLEN(""), 1);
50 1 EXPECT_EQ(ARRAYLEN("a"), 2);
51 1 EXPECT_EQ(ARRAYLEN("123456789"), 10);
52
53 1 UNUSED const char a2[] = {1, 2};
54 1 UNUSED const int a3[] = {1, 2, 3};
55 1 UNUSED const long long a4[] = {1, 2, 3, 4};
56 1 EXPECT_EQ(ARRAYLEN(a2), 2);
57 1 EXPECT_EQ(ARRAYLEN(a3), 3);
58 1 EXPECT_EQ(ARRAYLEN(a4), 4);
59
60 1 EXPECT_EQ(MIN(0, 1), 0);
61 1 EXPECT_EQ(MIN(99, 100), 99);
62 1 EXPECT_EQ(MIN(-10, 10), -10);
63
64 1 EXPECT_EQ(MAX(0, 1), 1);
65 1 EXPECT_EQ(MAX(99, 100), 100);
66 1 EXPECT_EQ(MAX(-10, 10), 10);
67
68 1 EXPECT_EQ(MAX4(1, 2, 3, 4), 4);
69 1 EXPECT_EQ(MAX4(4, 3, 2, 1), 4);
70 1 EXPECT_EQ(MAX4(-10, 10, 0, -20), 10);
71 1 EXPECT_EQ(MAX4(40, 41, 42, 41), 42);
72 1 EXPECT_EQ(MAX4(-10, -20, -50, -80), -10);
73
74 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(123U), UINT_MAX);
75 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(456UL), ULONG_MAX);
76 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(789ULL), ULLONG_MAX);
77 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE((size_t)123), SIZE_MAX);
78 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE((uintmax_t)456), UINTMAX_MAX);
79
80 1 int n = snprintf(NULL, 0, "%d", INT_MIN);
81 1 EXPECT_TRUE(n >= STRLEN("-2147483647"));
82 1 EXPECT_TRUE(DECIMAL_STR_MAX(int) > n);
83 1 n = snprintf(NULL, 0, "%llu", ULLONG_MAX);
84 1 EXPECT_TRUE(n >= STRLEN("18446744073709551615"));
85 1 EXPECT_TRUE(DECIMAL_STR_MAX(unsigned long long) > n);
86 1 }
87
88 1 static void test_is_power_of_2(TestContext *ctx)
89 {
90 1 EXPECT_TRUE(IS_POWER_OF_2(1));
91 1 EXPECT_TRUE(IS_POWER_OF_2(2));
92 1 EXPECT_TRUE(IS_POWER_OF_2(4));
93 1 EXPECT_TRUE(IS_POWER_OF_2(8));
94 1 EXPECT_TRUE(IS_POWER_OF_2(4096));
95 1 EXPECT_TRUE(IS_POWER_OF_2(8192));
96 1 EXPECT_TRUE(IS_POWER_OF_2(1ULL << 63));
97
98 1 EXPECT_FALSE(IS_POWER_OF_2(0));
99 1 EXPECT_FALSE(IS_POWER_OF_2(3));
100 1 EXPECT_FALSE(IS_POWER_OF_2(5));
101 1 EXPECT_FALSE(IS_POWER_OF_2(6));
102 1 EXPECT_FALSE(IS_POWER_OF_2(7));
103 1 EXPECT_FALSE(IS_POWER_OF_2(12));
104 1 EXPECT_FALSE(IS_POWER_OF_2(15));
105 1 EXPECT_FALSE(IS_POWER_OF_2(-2));
106 1 EXPECT_FALSE(IS_POWER_OF_2(-10));
107
108 1 const uintmax_t max_pow2 = UINTMAX_MAX & ~(UINTMAX_MAX >> 1);
109 1 EXPECT_TRUE(max_pow2 >= 1ULL << 63);
110 1 EXPECT_TRUE(IS_POWER_OF_2(max_pow2));
111 1 EXPECT_UINT_EQ(max_pow2 << 1, 0);
112
113
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1 times.
62 for (uintmax_t i = max_pow2; i > 4; i >>= 1) {
114 61 EXPECT_TRUE(IS_POWER_OF_2(i));
115
2/2
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 61 times.
244 for (uintmax_t j = 1; j < 4; j++) {
116 366 EXPECT_FALSE(IS_POWER_OF_2(i + j));
117 366 EXPECT_FALSE(IS_POWER_OF_2(i - j));
118 }
119 }
120 1 }
121
122 // Note: some of these tests are more for the sake of AddressSanitizer
123 // coverage than making actual assertions about the code
124 1 static void test_xmalloc(TestContext *ctx)
125 {
126 1 char *str = xmalloc(8);
127 1 ASSERT_NONNULL(str);
128 1 memcpy(str, "1234567", 8);
129 1 EXPECT_STREQ(str, "1234567");
130 1 free(str);
131
132 1 str = xstrdup("foobar");
133 1 EXPECT_STREQ(str, "foobar");
134 1 free(str);
135
136 1 str = xasprintf("%s %d", "xyz", 12340);
137 1 EXPECT_STREQ(str, "xyz 12340");
138 1 free(str);
139
140 1 str = xcalloc(4, 1);
141 1 ASSERT_NONNULL(str);
142 1 EXPECT_MEMEQ(str, 4, "\0\0\0\0", 4);
143 1 free(str);
144
145 1 str = xstrslice("one two three", 4, 7);
146 1 EXPECT_STREQ(str, "two");
147 1 free(str);
148
149 1 str = xstrjoin("foo", "-bar");
150 1 EXPECT_STREQ(str, "foo-bar");
151 1 free(str);
152
153 1 str = xnew0(char, 4);
154 1 ASSERT_NONNULL(str);
155 1 EXPECT_EQ(str[3], 0);
156 1 str = xrenew(str, 64);
157 1 ASSERT_NONNULL(str);
158 1 str[63] = 'p';
159 1 EXPECT_EQ(str[63], 'p');
160 1 free(str);
161 1 }
162
163 1 static void test_xstreq(TestContext *ctx)
164 {
165 1 EXPECT_TRUE(xstreq("foo", "foo"));
166 1 EXPECT_TRUE(xstreq("foo\0\n", "foo\0\0"));
167 1 EXPECT_TRUE(xstreq("\0foo", "\0bar"));
168 1 EXPECT_TRUE(xstreq(NULL, NULL));
169 1 EXPECT_FALSE(xstreq("foo", "bar"));
170 1 EXPECT_FALSE(xstreq("abc", "abcd"));
171 1 EXPECT_FALSE(xstreq("abcd", "abc"));
172 1 EXPECT_FALSE(xstreq(NULL, ""));
173 1 EXPECT_FALSE(xstreq("", NULL));
174 1 }
175
176 1 static void test_xstrrchr(TestContext *ctx)
177 {
178 1 static const char str[] = "12345432";
179 1 EXPECT_PTREQ(xstrrchr(str, '1'), str);
180 1 EXPECT_PTREQ(xstrrchr(str, '2'), str + 7);
181 1 EXPECT_PTREQ(xstrrchr(str, '5'), str + 4);
182 1 EXPECT_PTREQ(xstrrchr(str, '\0'), str + sizeof(str) - 1);
183 1 }
184
185 1 static void test_str_has_prefix(TestContext *ctx)
186 {
187 1 EXPECT_TRUE(str_has_prefix("foo", "foo"));
188 1 EXPECT_TRUE(str_has_prefix("foobar", "foo"));
189 1 EXPECT_TRUE(str_has_prefix("xyz", "xy"));
190 1 EXPECT_TRUE(str_has_prefix("a", "a"));
191 1 EXPECT_FALSE(str_has_prefix("foobar", "bar"));
192 1 EXPECT_FALSE(str_has_prefix("foo", "foobar"));
193 1 EXPECT_FALSE(str_has_prefix("xyz", "xyz."));
194 1 EXPECT_FALSE(str_has_prefix("ab", "b"));
195 1 EXPECT_FALSE(str_has_prefix("123", "xyz"));
196 1 }
197
198 1 static void test_str_has_suffix(TestContext *ctx)
199 {
200 1 EXPECT_TRUE(str_has_suffix("foo", "foo"));
201 1 EXPECT_TRUE(str_has_suffix("foobar", "bar"));
202 1 EXPECT_TRUE(str_has_suffix("1234", "234"));
203 1 EXPECT_TRUE(str_has_suffix("x", "x"));
204 1 EXPECT_TRUE(str_has_suffix("aa", "a"));
205 1 EXPECT_FALSE(str_has_suffix("foobar.", "bar"));
206 1 EXPECT_FALSE(str_has_suffix("foo", "foobar"));
207 1 EXPECT_FALSE(str_has_suffix("bar", "foobar"));
208 1 EXPECT_FALSE(str_has_suffix("foo", "bar"));
209 1 EXPECT_FALSE(str_has_suffix("bar", "foo"));
210 1 EXPECT_FALSE(str_has_suffix("123", "1234"));
211 1 EXPECT_FALSE(str_has_suffix("a", "aa"));
212 1 }
213
214 1 static void test_hex_decode(TestContext *ctx)
215 {
216 1 EXPECT_EQ(hex_decode('0'), 0);
217 1 EXPECT_EQ(hex_decode('1'), 1);
218 1 EXPECT_EQ(hex_decode('9'), 9);
219 1 EXPECT_EQ(hex_decode('a'), 10);
220 1 EXPECT_EQ(hex_decode('A'), 10);
221 1 EXPECT_EQ(hex_decode('f'), 15);
222 1 EXPECT_EQ(hex_decode('F'), 15);
223 1 EXPECT_EQ(hex_decode('g'), HEX_INVALID);
224 1 EXPECT_EQ(hex_decode('G'), HEX_INVALID);
225 1 EXPECT_EQ(hex_decode('@'), HEX_INVALID);
226 1 EXPECT_EQ(hex_decode('/'), HEX_INVALID);
227 1 EXPECT_EQ(hex_decode(':'), HEX_INVALID);
228 1 EXPECT_EQ(hex_decode(' '), HEX_INVALID);
229 1 EXPECT_EQ(hex_decode('~'), HEX_INVALID);
230 1 EXPECT_EQ(hex_decode('\0'), HEX_INVALID);
231 1 EXPECT_EQ(hex_decode(0xFF), HEX_INVALID);
232 1 }
233
234 1 static void test_hex_encode_byte(TestContext *ctx)
235 {
236 1 char buf[4] = {0};
237 1 EXPECT_EQ(hex_encode_byte(buf, 0x00), 2);
238 1 EXPECT_STREQ(buf, "00");
239 1 EXPECT_EQ(hex_encode_byte(buf, 0x05), 2);
240 1 EXPECT_STREQ(buf, "05");
241 1 EXPECT_EQ(hex_encode_byte(buf, 0x10), 2);
242 1 EXPECT_STREQ(buf, "10");
243 1 EXPECT_EQ(hex_encode_byte(buf, 0x1b), 2);
244 1 EXPECT_STREQ(buf, "1b");
245 1 EXPECT_EQ(hex_encode_byte(buf, 0xee), 2);
246 1 EXPECT_STREQ(buf, "ee");
247 1 EXPECT_EQ(hex_encode_byte(buf, 0xfe), 2);
248 1 EXPECT_STREQ(buf, "fe");
249 1 EXPECT_EQ(hex_encode_byte(buf, 0xff), 2);
250 1 EXPECT_STREQ(buf, "ff");
251 1 }
252
253 1 static void test_ascii(TestContext *ctx)
254 {
255 1 EXPECT_EQ(ascii_tolower('A'), 'a');
256 1 EXPECT_EQ(ascii_tolower('F'), 'f');
257 1 EXPECT_EQ(ascii_tolower('Z'), 'z');
258 1 EXPECT_EQ(ascii_tolower('a'), 'a');
259 1 EXPECT_EQ(ascii_tolower('f'), 'f');
260 1 EXPECT_EQ(ascii_tolower('z'), 'z');
261 1 EXPECT_EQ(ascii_tolower('9'), '9');
262 1 EXPECT_EQ(ascii_tolower('~'), '~');
263 1 EXPECT_EQ(ascii_tolower('\0'), '\0');
264
265 1 EXPECT_EQ(ascii_toupper('a'), 'A');
266 1 EXPECT_EQ(ascii_toupper('f'), 'F');
267 1 EXPECT_EQ(ascii_toupper('z'), 'Z');
268 1 EXPECT_EQ(ascii_toupper('A'), 'A');
269 1 EXPECT_EQ(ascii_toupper('F'), 'F');
270 1 EXPECT_EQ(ascii_toupper('Z'), 'Z');
271 1 EXPECT_EQ(ascii_toupper('9'), '9');
272 1 EXPECT_EQ(ascii_toupper('~'), '~');
273 1 EXPECT_EQ(ascii_toupper('\0'), '\0');
274
275 1 EXPECT_TRUE(ascii_isspace(' '));
276 1 EXPECT_TRUE(ascii_isspace('\t'));
277 1 EXPECT_TRUE(ascii_isspace('\r'));
278 1 EXPECT_TRUE(ascii_isspace('\n'));
279 1 EXPECT_FALSE(ascii_isspace('\0'));
280 1 EXPECT_FALSE(ascii_isspace('a'));
281 1 EXPECT_FALSE(ascii_isspace(0x7F));
282 1 EXPECT_FALSE(ascii_isspace(0x80));
283
284 1 EXPECT_TRUE(ascii_iscntrl('\0'));
285 1 EXPECT_TRUE(ascii_iscntrl('\a'));
286 1 EXPECT_TRUE(ascii_iscntrl('\b'));
287 1 EXPECT_TRUE(ascii_iscntrl('\t'));
288 1 EXPECT_TRUE(ascii_iscntrl('\n'));
289 1 EXPECT_TRUE(ascii_iscntrl('\v'));
290 1 EXPECT_TRUE(ascii_iscntrl('\f'));
291 1 EXPECT_TRUE(ascii_iscntrl('\r'));
292 1 EXPECT_TRUE(ascii_iscntrl(0x0E));
293 1 EXPECT_TRUE(ascii_iscntrl(0x1F));
294 1 EXPECT_TRUE(ascii_iscntrl(0x7F));
295 1 EXPECT_FALSE(ascii_iscntrl(' '));
296 1 EXPECT_FALSE(ascii_iscntrl('a'));
297 1 EXPECT_FALSE(ascii_iscntrl(0x7E));
298 1 EXPECT_FALSE(ascii_iscntrl(0x80));
299 1 EXPECT_FALSE(ascii_iscntrl(0xFF));
300
301 1 EXPECT_TRUE(ascii_isdigit('0'));
302 1 EXPECT_TRUE(ascii_isdigit('1'));
303 1 EXPECT_TRUE(ascii_isdigit('9'));
304 1 EXPECT_FALSE(ascii_isdigit('a'));
305 1 EXPECT_FALSE(ascii_isdigit('f'));
306 1 EXPECT_FALSE(ascii_isdigit('/'));
307 1 EXPECT_FALSE(ascii_isdigit(':'));
308 1 EXPECT_FALSE(ascii_isdigit('\0'));
309 1 EXPECT_FALSE(ascii_isdigit(0xFF));
310
311 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\0'));
312 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\a'));
313 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\b'));
314 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x0E));
315 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x1F));
316 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x7F));
317 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\t'));
318 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\n'));
319 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\r'));
320 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(' '));
321 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('a'));
322 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0x7E));
323 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0x80));
324 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0xFF));
325
326 1 EXPECT_TRUE(ascii_isprint(' '));
327 1 EXPECT_TRUE(ascii_isprint('!'));
328 1 EXPECT_TRUE(ascii_isprint('/'));
329 1 EXPECT_TRUE(ascii_isprint('a'));
330 1 EXPECT_TRUE(ascii_isprint('z'));
331 1 EXPECT_TRUE(ascii_isprint('0'));
332 1 EXPECT_TRUE(ascii_isprint('_'));
333 1 EXPECT_TRUE(ascii_isprint('~'));
334 1 EXPECT_FALSE(ascii_isprint('\0'));
335 1 EXPECT_FALSE(ascii_isprint('\t'));
336 1 EXPECT_FALSE(ascii_isprint('\n'));
337 1 EXPECT_FALSE(ascii_isprint('\r'));
338 1 EXPECT_FALSE(ascii_isprint(0x1F));
339 1 EXPECT_FALSE(ascii_isprint(0x7F));
340 1 EXPECT_FALSE(ascii_isprint(0x80));
341 1 EXPECT_FALSE(ascii_isprint(0xFF));
342
343 1 EXPECT_TRUE(is_word_byte('a'));
344 1 EXPECT_TRUE(is_word_byte('z'));
345 1 EXPECT_TRUE(is_word_byte('A'));
346 1 EXPECT_TRUE(is_word_byte('Z'));
347 1 EXPECT_TRUE(is_word_byte('0'));
348 1 EXPECT_TRUE(is_word_byte('9'));
349 1 EXPECT_TRUE(is_word_byte('_'));
350 1 EXPECT_TRUE(is_word_byte(0x80));
351 1 EXPECT_TRUE(is_word_byte(0xFF));
352 1 EXPECT_FALSE(is_word_byte('-'));
353 1 EXPECT_FALSE(is_word_byte('.'));
354 1 EXPECT_FALSE(is_word_byte(0x7F));
355 1 EXPECT_FALSE(is_word_byte(0x00));
356
357 1 EXPECT_TRUE(is_regex_special_char('$'));
358 1 EXPECT_TRUE(is_regex_special_char('('));
359 1 EXPECT_TRUE(is_regex_special_char(')'));
360 1 EXPECT_TRUE(is_regex_special_char('*'));
361 1 EXPECT_TRUE(is_regex_special_char('+'));
362 1 EXPECT_TRUE(is_regex_special_char('.'));
363 1 EXPECT_TRUE(is_regex_special_char('?'));
364 1 EXPECT_TRUE(is_regex_special_char('['));
365 1 EXPECT_TRUE(is_regex_special_char('^'));
366 1 EXPECT_TRUE(is_regex_special_char('{'));
367 1 EXPECT_TRUE(is_regex_special_char('|'));
368 1 EXPECT_TRUE(is_regex_special_char('\\'));
369 1 EXPECT_FALSE(is_regex_special_char('"'));
370 1 EXPECT_FALSE(is_regex_special_char('&'));
371 1 EXPECT_FALSE(is_regex_special_char(','));
372 1 EXPECT_FALSE(is_regex_special_char('0'));
373 1 EXPECT_FALSE(is_regex_special_char('@'));
374 1 EXPECT_FALSE(is_regex_special_char('A'));
375 1 EXPECT_FALSE(is_regex_special_char('\''));
376 1 EXPECT_FALSE(is_regex_special_char(']'));
377 1 EXPECT_FALSE(is_regex_special_char('_'));
378 1 EXPECT_FALSE(is_regex_special_char('z'));
379 1 EXPECT_FALSE(is_regex_special_char('}'));
380 1 EXPECT_FALSE(is_regex_special_char('~'));
381 1 EXPECT_FALSE(is_regex_special_char(0x00));
382 1 EXPECT_FALSE(is_regex_special_char(0x80));
383 1 EXPECT_FALSE(is_regex_special_char(0xFF));
384
385 1 EXPECT_TRUE(ascii_streq_icase("", ""));
386 1 EXPECT_TRUE(ascii_streq_icase("a", "a"));
387 1 EXPECT_TRUE(ascii_streq_icase("a", "A"));
388 1 EXPECT_TRUE(ascii_streq_icase("z", "Z"));
389 1 EXPECT_TRUE(ascii_streq_icase("cx", "CX"));
390 1 EXPECT_TRUE(ascii_streq_icase("ABC..XYZ", "abc..xyz"));
391 1 EXPECT_TRUE(ascii_streq_icase("Ctrl", "CTRL"));
392 1 EXPECT_FALSE(ascii_streq_icase("a", ""));
393 1 EXPECT_FALSE(ascii_streq_icase("", "a"));
394 1 EXPECT_FALSE(ascii_streq_icase("Ctrl+", "CTRL"));
395 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "CTRL+"));
396 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "Ctr"));
397 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "CtrM"));
398
399 1 EXPECT_EQ(ascii_strcmp_icase("", ""), 0);
400 1 EXPECT_EQ(ascii_strcmp_icase("A", "A"), 0);
401 1 EXPECT_EQ(ascii_strcmp_icase("xyz", ""), 'x');
402 1 EXPECT_EQ(ascii_strcmp_icase("", "xyz"), -'x');
403 1 EXPECT_EQ(ascii_strcmp_icase("xyz", "xy"), 'z');
404 1 EXPECT_EQ(ascii_strcmp_icase("xy", "xyz"), -'z');
405 1 EXPECT_EQ(ascii_strcmp_icase("\xFF", "\xFE"), 1);
406 1 EXPECT_EQ(ascii_strcmp_icase("\xFE", "\xFF"), -1);
407 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\xC1", "\x80\xFF\x01"), 0xC0);
408 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\x01", "\x80\xFF\xC1"), -0xC0);
409 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\x01", "\x80"), 0xFF);
410 1 EXPECT_EQ(ascii_strcmp_icase("\x80", "\x80\xFF\x01"), -0xFF);
411
412 // Query the current locale
413 1 const char *locale = setlocale(LC_CTYPE, NULL);
414 1 ASSERT_NONNULL(locale);
415
416 // Copy the locale string (which may be in static storage)
417 1 char *saved_locale = xstrdup(locale);
418
419 // Check that the ascii_is*() functions behave like their corresponding
420 // <ctype.h> macros, when in the standard "C" locale
421 1 ASSERT_NONNULL(setlocale(LC_CTYPE, "C"));
422
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 1 times.
258 for (int i = -1; i < 256; i++) {
423 257 EXPECT_EQ(ascii_isalpha(i), !!isalpha(i));
424 257 EXPECT_EQ(ascii_isalnum(i), !!isalnum(i));
425 257 EXPECT_EQ(ascii_islower(i), !!islower(i));
426 257 EXPECT_EQ(ascii_isupper(i), !!isupper(i));
427 257 EXPECT_EQ(ascii_iscntrl(i), !!iscntrl(i));
428 257 EXPECT_EQ(ascii_isdigit(i), !!isdigit(i));
429 257 EXPECT_EQ(ascii_isblank(i), !!isblank(i));
430 257 EXPECT_EQ(ascii_isprint(i), !!isprint(i));
431 257 EXPECT_EQ(u_is_ascii_upper(i), !!isupper(i));
432 257 EXPECT_EQ(hex_decode(i) <= 0xF, !!isxdigit(i));
433 461 EXPECT_EQ(is_alpha_or_underscore(i), !!isalpha(i) || i == '_');
434 451 EXPECT_EQ(is_alnum_or_underscore(i), !!isalnum(i) || i == '_');
435
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 2 times.
257 if (i != '\v' && i != '\f') {
436 255 EXPECT_EQ(ascii_isspace(i), !!isspace(i));
437 255 EXPECT_EQ(ascii_is_nonspace_cntrl(i), !!iscntrl(i) && !isspace(i));
438 }
439
2/2
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 1 times.
255 if (i != -1) {
440 256 EXPECT_EQ(ascii_tolower(i), tolower(i));
441 256 EXPECT_EQ(ascii_toupper(i), toupper(i));
442 }
443 }
444
445 // Restore the original locale
446 1 ASSERT_NONNULL(setlocale(LC_CTYPE, saved_locale));
447 1 free(saved_locale);
448 1 }
449
450 1 static void test_mem_equal_icase(TestContext *ctx)
451 {
452 1 const char s1[8] = "Ctrl+Up";
453 1 const char s2[8] = "CTRL+U_";
454 1 EXPECT_TRUE(mem_equal_icase(NULL, NULL, 0));
455 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 0));
456 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 1));
457 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 2));
458 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 3));
459 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 4));
460 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 5));
461 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 6));
462 1 EXPECT_FALSE(mem_equal_icase(s1, s2, 7));
463 1 EXPECT_FALSE(mem_equal_icase(s1, s2, 8));
464 1 }
465
466 1 static void test_base64_decode(TestContext *ctx)
467 {
468 1 EXPECT_EQ(base64_decode('A'), 0);
469 1 EXPECT_EQ(base64_decode('Z'), 25);
470 1 EXPECT_EQ(base64_decode('a'), 26);
471 1 EXPECT_EQ(base64_decode('z'), 51);
472 1 EXPECT_EQ(base64_decode('0'), 52);
473 1 EXPECT_EQ(base64_decode('9'), 61);
474 1 EXPECT_EQ(base64_decode('+'), 62);
475 1 EXPECT_EQ(base64_decode('/'), 63);
476 1 EXPECT_EQ(base64_decode('='), BASE64_PADDING);
477 1 EXPECT_EQ(base64_decode(0x00), BASE64_INVALID);
478 1 EXPECT_EQ(base64_decode(0xFF), BASE64_INVALID);
479
480 1 EXPECT_EQ(base64_encode_table[0], 'A');
481 1 EXPECT_EQ(base64_encode_table[25], 'Z');
482 1 EXPECT_EQ(base64_encode_table[26], 'a');
483 1 EXPECT_EQ(base64_encode_table[51], 'z');
484 1 EXPECT_EQ(base64_encode_table[52], '0');
485 1 EXPECT_EQ(base64_encode_table[61], '9');
486 1 EXPECT_EQ(base64_encode_table[62], '+');
487 1 EXPECT_EQ(base64_encode_table[63], '/');
488
489
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1 times.
27 for (unsigned int i = 'A'; i <= 'Z'; i++) {
490 26 IEXPECT_EQ(base64_decode(i), i - 'A');
491 }
492
493
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1 times.
27 for (unsigned int i = 'a'; i <= 'z'; i++) {
494 26 IEXPECT_EQ(base64_decode(i), (i - 'a') + 26);
495 }
496
497
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 for (unsigned int i = '0'; i <= '9'; i++) {
498 10 IEXPECT_EQ(base64_decode(i), (i - '0') + 52);
499 }
500
501
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 1 times.
257 for (unsigned int i = 0; i < 256; i++) {
502 256 unsigned int val = base64_decode(i);
503
4/4
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 192 times.
256 if (ascii_isalnum(i) || i == '+' || i == '/') {
504 64 IEXPECT_EQ(val, val & 63);
505 64 IEXPECT_EQ(i, base64_encode_table[val & 63]);
506 } else {
507 192 IEXPECT_EQ(val, val & 192);
508 }
509 256 IEXPECT_EQ(val, base64_decode_branchy(i));
510 }
511 1 }
512
513 1 static void test_base64_encode_block(TestContext *ctx)
514 {
515 1 char buf[16];
516 1 size_t n = base64_encode_block(STRN("xyz"), buf, sizeof(buf));
517 1 EXPECT_MEMEQ(buf, n, "eHl6", 4);
518
519 1 n = base64_encode_block(STRN("123456"), buf, sizeof(buf));
520 1 EXPECT_MEMEQ(buf, n, "MTIzNDU2", 8);
521
522 1 n = base64_encode_block(STRN("a == *x++"), buf, sizeof(buf));
523 1 EXPECT_MEMEQ(buf, n, "YSA9PSAqeCsr", 12);
524 1 }
525
526 1 static void test_base64_encode_final(TestContext *ctx)
527 {
528 1 char buf[4];
529 1 base64_encode_final(STRN("+"), buf);
530 1 EXPECT_MEMEQ(buf, 4, "Kw==", 4);
531
532 1 base64_encode_final(STRN(".."), buf);
533 1 EXPECT_MEMEQ(buf, 4, "Li4=", 4);
534
535 1 base64_encode_final(STRN("~."), buf);
536 1 EXPECT_MEMEQ(buf, 4, "fi4=", 4);
537
538 1 base64_encode_final(STRN("\xC2\xA9"), buf);
539 1 EXPECT_MEMEQ(buf, 4, "wqk=", 4);
540 1 }
541
542 1 static void test_string(TestContext *ctx)
543 {
544 1 String s = STRING_INIT;
545 1 EXPECT_EQ(s.len, 0);
546 1 EXPECT_EQ(s.alloc, 0);
547 1 EXPECT_NULL(s.buffer);
548
549 1 char *cstr = string_clone_cstring(&s);
550 1 EXPECT_STREQ(cstr, "");
551 1 free(cstr);
552 1 EXPECT_EQ(s.len, 0);
553 1 EXPECT_EQ(s.alloc, 0);
554 1 EXPECT_NULL(s.buffer);
555
556 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 0x1F4AF), 4);
557 1 EXPECT_EQ(s.len, 4);
558 1 EXPECT_STREQ(string_borrow_cstring(&s), "\xF0\x9F\x92\xAF");
559
560 1 string_append_cstring(&s, "test");
561 1 EXPECT_EQ(s.len, 8);
562 1 EXPECT_STREQ(string_borrow_cstring(&s), "\xF0\x9F\x92\xAFtest");
563
564 1 string_remove(&s, 0, 5);
565 1 EXPECT_EQ(s.len, 3);
566 1 EXPECT_STREQ(string_borrow_cstring(&s), "est");
567
568 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 't'), 1);
569 1 EXPECT_EQ(s.len, 4);
570 1 EXPECT_STREQ(string_borrow_cstring(&s), "test");
571
572 1 EXPECT_EQ(string_clear(&s), 4);
573 1 EXPECT_EQ(s.len, 0);
574 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 0x0E01), 3);
575 1 EXPECT_EQ(s.len, 3);
576 1 EXPECT_STREQ(string_borrow_cstring(&s), "\xE0\xB8\x81");
577
578 1 EXPECT_EQ(string_clear(&s), 3);
579 1 string_sprintf(&s, "%d %s\n", 88, "test");
580 1 EXPECT_EQ(s.len, 8);
581 1 EXPECT_STREQ(string_borrow_cstring(&s), "88 test\n");
582
583 1 string_free(&s);
584 1 EXPECT_EQ(s.len, 0);
585 1 EXPECT_EQ(s.alloc, 0);
586 1 EXPECT_NULL(s.buffer);
587
588
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1 times.
41 for (size_t i = 0; i < 40; i++) {
589 40 string_append_byte(&s, 'a');
590 }
591
592 1 EXPECT_EQ(s.len, 40);
593 1 cstr = string_steal_cstring(&s);
594 1 EXPECT_EQ(s.len, 0);
595 1 EXPECT_EQ(s.alloc, 0);
596 1 EXPECT_NULL(s.buffer);
597 1 EXPECT_STREQ(cstr, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
598 1 free(cstr);
599
600 1 s = string_new(12);
601 1 EXPECT_EQ(s.len, 0);
602 1 EXPECT_EQ(s.alloc, 16);
603 1 ASSERT_NONNULL(s.buffer);
604
605 1 string_append_cstring(&s, "123");
606 1 EXPECT_STREQ(string_borrow_cstring(&s), "123");
607 1 EXPECT_EQ(s.len, 3);
608
609 1 string_append_string(&s, &s);
610 1 EXPECT_STREQ(string_borrow_cstring(&s), "123123");
611 1 EXPECT_EQ(s.len, 6);
612
613 1 string_insert_buf(&s, 2, STRN("foo"));
614 1 EXPECT_STREQ(string_borrow_cstring(&s), "12foo3123");
615 1 EXPECT_EQ(s.len, 9);
616
617 1 cstr = string_clone_cstring(&s);
618 1 EXPECT_STREQ(cstr, "12foo3123");
619
620 1 EXPECT_EQ(string_insert_codepoint(&s, 0, '>'), 1);
621 1 EXPECT_STREQ(string_borrow_cstring(&s), ">12foo3123");
622 1 EXPECT_EQ(s.len, 10);
623
624 1 string_replace_byte(&s, '1', '_');
625 1 EXPECT_STREQ(string_borrow_cstring(&s), ">_2foo3_23");
626 1 string_replace_byte(&s, '_', '.');
627 1 string_replace_byte(&s, '2', '+');
628 1 string_replace_byte(&s, '3', '$');
629 1 EXPECT_STREQ(string_borrow_cstring(&s), ">.+foo$.+$");
630
631 1 string_free(&s);
632 1 EXPECT_NULL(s.buffer);
633 1 EXPECT_EQ(s.len, 0);
634 1 EXPECT_EQ(s.alloc, 0);
635 1 EXPECT_STREQ(cstr, "12foo3123");
636 1 free(cstr);
637
638 // This is mostly for UBSan coverage
639 // See also: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3261.pdf
640 1 s = string_new(0);
641 1 EXPECT_NULL(s.buffer);
642 1 EXPECT_EQ(s.len, 0);
643 1 EXPECT_EQ(s.alloc, 0);
644 1 string_append_buf(&s, NULL, 0);
645 1 string_insert_buf(&s, 0, NULL, 0);
646 1 string_append_memset(&s, 'q', 0);
647 1 string_replace_byte(&s, 'q', 'z');
648 1 string_remove(&s, 0, 0);
649 1 EXPECT_NULL(s.buffer);
650 1 EXPECT_EQ(s.len, 0);
651 1 EXPECT_EQ(s.alloc, 0);
652 1 string_free(&s);
653 1 }
654
655 1 static void test_string_view(TestContext *ctx)
656 {
657 1 StringView sv = STRING_VIEW("testing");
658 1 EXPECT_TRUE(strview_equal_cstring(&sv, "testing"));
659 1 EXPECT_FALSE(strview_equal_cstring(&sv, "testin"));
660 1 EXPECT_FALSE(strview_equal_cstring(&sv, "TESTING"));
661 1 EXPECT_TRUE(strview_has_prefix(&sv, "test"));
662 1 EXPECT_TRUE(strview_has_prefix_icase(&sv, "TEst"));
663 1 EXPECT_FALSE(strview_has_prefix(&sv, "TEst"));
664 1 EXPECT_FALSE(strview_has_prefix_icase(&sv, "TEst_"));
665
666 1 sv = string_view(sv.data, sv.length);
667 1 EXPECT_TRUE(strview_equal(&sv, &sv));
668 1 sv = string_view(STRN("\0test\0 ..."));
669 1 EXPECT_TRUE(strview_equal_strn(&sv, "\0test\0 ...", 10));
670
671 1 sv = strview_from_cstring("foobar");
672 1 EXPECT_TRUE(strview_equal_cstring(&sv, "foobar"));
673 1 EXPECT_TRUE(strview_has_prefix(&sv, "foo"));
674 1 EXPECT_FALSE(strview_equal_cstring(&sv, "foo"));
675
676 1 sv = strview_from_cstring("\t \t\t ");
677 1 EXPECT_TRUE(strview_isblank(&sv));
678 1 sv.length = 0;
679 1 EXPECT_TRUE(strview_isblank(&sv));
680 1 sv = strview_from_cstring(" \t . ");
681 1 EXPECT_FALSE(strview_isblank(&sv));
682 1 sv = strview_from_cstring("\n");
683 1 EXPECT_FALSE(strview_isblank(&sv));
684 1 sv = strview_from_cstring(" \r ");
685 1 EXPECT_FALSE(strview_isblank(&sv));
686
687 1 sv = strview_from_cstring(" \t\t \ttrim test \t\t");
688 1 strview_trim(&sv);
689 1 EXPECT_TRUE(strview_equal_cstring(&sv, "trim test"));
690
691 1 sv = string_view(NULL, 0);
692 1 EXPECT_NULL(strview_memrchr(&sv, '.'));
693 1 EXPECT_NULL(strview_memchr(&sv, '.'));
694 1 EXPECT_TRUE(strview_equal(&sv, &sv));
695 1 EXPECT_FALSE(strview_contains_char_type(&sv, ASCII_DIGIT));
696 1 EXPECT_TRUE(strview_isblank(&sv));
697 1 EXPECT_EQ(strview_trim_left(&sv), 0);
698 1 EXPECT_TRUE(strview_equal_cstring(&sv, ""));
699 1 EXPECT_TRUE(strview_equal_cstring_icase(&sv, ""));
700 1 EXPECT_TRUE(strview_has_prefix(&sv, ""));
701 1 EXPECT_TRUE(strview_has_suffix(&sv, ""));
702 1 EXPECT_TRUE(strview_has_prefix_icase(&sv, ""));
703
704 // Call these 3 for ASan/UBSan coverage:
705 1 strview_trim_right(&sv);
706 1 strview_trim(&sv);
707 1 strview_remove_prefix(&sv, 0);
708 1 EXPECT_NULL(sv.data);
709 1 EXPECT_EQ(sv.length, 0);
710
711 1 sv = strview_from_cstring("prefix - suffix");
712 1 EXPECT_PTREQ(strview_memchr(&sv, '-'), strview_memrchr(&sv, '-'));
713 1 EXPECT_PTREQ(strview_memchr(&sv, 'x'), sv.data + 5);
714 1 EXPECT_PTREQ(strview_memrchr(&sv, 'x'), sv.data + 14);
715 1 EXPECT_PTREQ(strview_memrchr(&sv, '@'), NULL);
716 1 EXPECT_EQ(strview_memrchr_idx(&sv, 'p'), 0);
717 1 EXPECT_EQ(strview_memrchr_idx(&sv, 'x'), 14);
718 1 EXPECT_EQ(strview_memrchr_idx(&sv, '@'), -1);
719 1 }
720
721 1 static void test_strview_has_suffix(TestContext *ctx)
722 {
723 1 StringView sv = strview_from_cstring("foobar");
724 1 EXPECT_TRUE(strview_has_suffix(&sv, "foobar"));
725 1 EXPECT_TRUE(strview_has_suffix(&sv, "bar"));
726 1 EXPECT_TRUE(strview_has_suffix(&sv, "r"));
727 1 EXPECT_TRUE(strview_has_suffix(&sv, ""));
728 1 EXPECT_FALSE(strview_has_suffix(&sv, "foo"));
729 1 EXPECT_FALSE(strview_has_suffix(&sv, "foobars"));
730
731 1 sv.length--;
732 1 EXPECT_FALSE(strview_has_suffix(&sv, "bar"));
733 1 EXPECT_TRUE(strview_has_suffix(&sv, "ba"));
734 1 EXPECT_TRUE(strview_has_strn_suffix(&sv, NULL, 0));
735
736 1 sv.length = 0;
737 1 EXPECT_TRUE(strview_has_suffix(&sv, ""));
738 1 EXPECT_FALSE(strview_has_suffix(&sv, "f"));
739 1 EXPECT_TRUE(strview_has_strn_suffix(&sv, NULL, 0));
740
741 1 sv.data = NULL;
742 1 EXPECT_TRUE(strview_has_suffix(&sv, ""));
743 1 EXPECT_FALSE(strview_has_suffix(&sv, "f"));
744 1 EXPECT_TRUE(strview_has_strn_suffix(&sv, NULL, 0));
745 1 }
746
747 1 static void test_strview_remove_matching(TestContext *ctx)
748 {
749 1 StringView sv = STRING_VIEW("ABCDEFGHIJKLMN");
750 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, "ABC"));
751 1 EXPECT_TRUE(strview_equal_cstring(&sv, "DEFGHIJKLMN"));
752
753 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, "KLMN"));
754 1 EXPECT_TRUE(strview_equal_cstring(&sv, "DEFGHIJ"));
755
756 1 EXPECT_FALSE(strview_remove_matching_prefix(&sv, "A"));
757 1 EXPECT_FALSE(strview_remove_matching_suffix(&sv, "K"));
758 1 EXPECT_TRUE(strview_equal_cstring(&sv, "DEFGHIJ"));
759
760 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, ""));
761 1 EXPECT_TRUE(strview_equal_cstring(&sv, "DEFGHIJ"));
762
763 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, ""));
764 1 EXPECT_TRUE(strview_equal_cstring(&sv, "DEFGHIJ"));
765
766 1 sv.length = 0;
767 1 sv.data = NULL;
768 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, ""));
769 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, ""));
770 1 EXPECT_FALSE(strview_remove_matching_prefix(&sv, "pre"));
771 1 EXPECT_FALSE(strview_remove_matching_suffix(&sv, "suf"));
772 1 EXPECT_EQ(sv.length, 0);
773 1 EXPECT_NULL(sv.data);
774 1 EXPECT_TRUE(strview_equal_cstring(&sv, ""));
775 1 }
776
777 1 static void test_get_delim(TestContext *ctx)
778 {
779 1 static const char input[] = "-x-y-foo--bar--";
780 1 static const char parts[][4] = {"", "x", "y", "foo", "", "bar", "", ""};
781 1 const size_t nparts = ARRAYLEN(parts);
782 1 const size_t part_size = ARRAYLEN(parts[0]);
783
784 1 size_t idx = 0;
785
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 for (size_t pos = 0, len = sizeof(input) - 1; pos < len; idx++) {
786 7 const StringView sv = get_delim(input, &pos, len, '-');
787 7 ASSERT_TRUE(idx < nparts);
788 7 ASSERT_TRUE(parts[idx][part_size - 1] == '\0');
789 7 EXPECT_TRUE(strview_equal_cstring(&sv, parts[idx]));
790 }
791
792 1 EXPECT_EQ(idx, nparts - 1);
793 1 }
794
795 1 static void test_get_delim_str(TestContext *ctx)
796 {
797 1 char str[] = "word1-word2-end-";
798 1 size_t len = sizeof(str) - 1;
799 1 ASSERT_EQ(str[len - 1], '-'); // Last character in bounds is a delimiter
800
801 1 size_t pos = 0;
802 1 const char *substr = get_delim_str(str, &pos, len, '-');
803 1 EXPECT_STREQ(substr, "word1");
804 1 EXPECT_EQ(pos, 6);
805
806 1 substr = get_delim_str(str, &pos, len, '-');
807 1 EXPECT_STREQ(substr, "word2");
808 1 EXPECT_EQ(pos, 12);
809
810 1 substr = get_delim_str(str, &pos, len, '-');
811 1 EXPECT_STREQ(substr, "end");
812 1 EXPECT_EQ(pos, 16);
813
814 // Note: str2 is not null-terminated and there are no delimiters present,
815 // but there's one extra, writable byte in the buffer that falls outside
816 // the length bound
817 1 char str2[16] = "no delimiter...!";
818 1 len = sizeof(str2) - 1;
819 1 ASSERT_EQ(str2[len], '!');
820 1 pos = 0;
821 1 substr = get_delim_str(str2, &pos, len, '-');
822 1 EXPECT_STREQ(substr, "no delimiter...");
823 1 EXPECT_EQ(pos, len);
824 1 }
825
826 1 static void test_str_replace_byte(TestContext *ctx)
827 {
828 1 char str[] = " a b c d e f g ";
829 1 EXPECT_EQ(str_replace_byte(str, ' ', '-'), strlen(str));
830 1 EXPECT_STREQ(str, "-a-b-c--d-e--f-g-");
831 1 }
832
833 1 static void test_strn_replace_byte(TestContext *ctx)
834 {
835 1 static const char expected[] = "||a|b|c||\n\0\0|d|e|f|||\0g|h||\0\0";
836 1 char str[] = /* ........... */ "..a.b.c..\n\0\0.d.e.f...\0g.h..\0\0";
837 1 strn_replace_byte(str, sizeof(str), '.', '|');
838 1 EXPECT_MEMEQ(str, sizeof(str), expected, sizeof(expected));
839 1 }
840
841 1 static void test_size_str_width(TestContext *ctx)
842 {
843 1 EXPECT_EQ(size_str_width(0), 1);
844 1 EXPECT_EQ(size_str_width(1), 1);
845 1 EXPECT_EQ(size_str_width(9), 1);
846 1 EXPECT_EQ(size_str_width(19), 2);
847 1 EXPECT_EQ(size_str_width(425), 3);
848 1 EXPECT_EQ(size_str_width(12345), 5);
849 1 EXPECT_EQ(size_str_width(2147483647), 10);
850 1 }
851
852 1 static void test_buf_parse_uintmax(TestContext *ctx)
853 {
854 1 uintmax_t val;
855 1 char max[DECIMAL_STR_MAX(val) + 2];
856 1 size_t max_len = xsnprintf(max, sizeof max, "%ju", UINTMAX_MAX);
857
858 1 val = 11;
859 1 EXPECT_EQ(buf_parse_uintmax(max, max_len, &val), max_len);
860 1 EXPECT_UINT_EQ(val, UINTMAX_MAX);
861
862 1 val = 22;
863 1 max[max_len++] = '9';
864 1 EXPECT_EQ(buf_parse_uintmax(max, max_len, &val), 0);
865 1 EXPECT_EQ(val, 22);
866
867 1 val = 33;
868 1 max[max_len++] = '7';
869 1 EXPECT_EQ(buf_parse_uintmax(max, max_len, &val), 0);
870 1 EXPECT_EQ(val, 33);
871
872 1 EXPECT_EQ(buf_parse_uintmax("0", 1, &val), 1);
873 1 EXPECT_EQ(val, 0);
874
875 1 EXPECT_EQ(buf_parse_uintmax("0019817", 8, &val), 7);
876 1 EXPECT_EQ(val, 19817);
877
878 1 EXPECT_EQ(buf_parse_uintmax("0098765", 5, &val), 5);
879 1 EXPECT_EQ(val, 987);
880
881 1 char buf[4] = " 90/";
882 1 buf[0] = CHAR_MAX;
883 1 EXPECT_EQ(buf_parse_uintmax(buf, 4, &val), 0);
884
885
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 1 times.
256 for (char c = CHAR_MIN; c < CHAR_MAX; c++) {
886 255 buf[0] = c;
887
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 10 times.
255 if (!ascii_isdigit(c)) {
888 245 EXPECT_EQ(buf_parse_uintmax(buf, 4, &val), 0);
889 245 continue;
890 }
891 10 val = 337;
892 10 EXPECT_EQ(buf_parse_uintmax(buf, 0, &val), 0);
893 10 EXPECT_EQ(val, 337);
894 10 EXPECT_EQ(buf_parse_uintmax(buf, 1, &val), 1);
895 10 EXPECT_TRUE(val <= 9);
896 10 EXPECT_EQ(buf_parse_uintmax(buf, 2, &val), 2);
897 10 EXPECT_TRUE(val >= 9);
898 10 EXPECT_TRUE(val <= 99);
899 10 EXPECT_EQ(buf_parse_uintmax(buf, 3, &val), 3);
900 10 EXPECT_TRUE(val >= 90);
901 10 EXPECT_TRUE(val <= 990);
902 10 const uintmax_t prev = val;
903 10 EXPECT_EQ(buf_parse_uintmax(buf, 4, &val), 3);
904 10 EXPECT_EQ(val, prev);
905 }
906 1 }
907
908 1 static void test_buf_parse_ulong(TestContext *ctx)
909 {
910 1 unsigned long val;
911 1 char max[DECIMAL_STR_MAX(val) + 1];
912 1 size_t max_len = xsnprintf(max, sizeof max, "%lu", ULONG_MAX);
913
914 1 val = 88;
915 1 EXPECT_EQ(buf_parse_ulong(max, max_len, &val), max_len);
916 1 EXPECT_UINT_EQ(val, ULONG_MAX);
917
918 1 val = 99;
919 1 max[max_len++] = '1';
920 1 EXPECT_EQ(buf_parse_ulong(max, max_len, &val), 0);
921 1 EXPECT_EQ(val, 99);
922
923 1 EXPECT_EQ(buf_parse_ulong("0", 1, &val), 1);
924 1 EXPECT_EQ(val, 0);
925
926 1 EXPECT_EQ(buf_parse_ulong("9876", 4, &val), 4);
927 1 EXPECT_EQ(val, 9876);
928 1 }
929
930 1 static void test_buf_parse_size(TestContext *ctx)
931 {
932 1 size_t val;
933 1 char max[DECIMAL_STR_MAX(val) + 1];
934 1 size_t max_len = xsnprintf(max, sizeof max, "%zu", SIZE_MAX);
935
936 1 val = 14;
937 1 EXPECT_EQ(buf_parse_size(max, max_len, &val), max_len);
938 1 EXPECT_UINT_EQ(val, SIZE_MAX);
939
940 1 val = 88;
941 1 max[max_len++] = '0';
942 1 EXPECT_EQ(buf_parse_size(max, max_len, &val), 0);
943 1 EXPECT_EQ(val, 88);
944 1 }
945
946 1 static void test_buf_parse_hex_uint(TestContext *ctx)
947 {
948 1 unsigned int val;
949 1 char buf[HEX_STR_MAX(val) + 1];
950 1 size_t buf_len = xsnprintf(buf, sizeof buf, "%x", UINT_MAX);
951 1 val = 0x90;
952 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len, &val), buf_len);
953 1 EXPECT_UINT_EQ(val, UINT_MAX);
954
955 1 buf_len = xsnprintf(buf, sizeof buf, "1%x", UINT_MAX);
956 1 val = 0x100;
957 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len, &val), 0);
958 1 EXPECT_UINT_EQ(val, 0x100);
959
960 1 buf_len = xsnprintf(buf, sizeof buf, "%xg", UINT_MAX);
961 1 val = 0x110;
962 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len, &val), buf_len - 1);
963 1 EXPECT_UINT_EQ(val, UINT_MAX);
964
965 1 buf_len = xsnprintf(buf, sizeof buf, "%xf", UINT_MAX);
966 1 val = 0x120;
967 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len, &val), 0);
968 1 EXPECT_UINT_EQ(val, 0x120);
969
970 1 buf_len = sizeof(buf);
971 1 memset(buf, '0', buf_len);
972 1 val = 0x130;
973 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len, &val), buf_len);
974 1 EXPECT_UINT_EQ(val, 0);
975
976 1 val = 0x140;
977 1 EXPECT_EQ(buf_parse_hex_uint(buf, buf_len - 2, &val), buf_len - 2);
978 1 EXPECT_UINT_EQ(val, 0);
979
980 1 val = 0x150;
981 1 EXPECT_EQ(buf_parse_hex_uint(STRN("12345678"), &val), 8);
982 1 EXPECT_UINT_EQ(val, 0x12345678);
983
984 1 val = 0x160;
985 1 EXPECT_EQ(buf_parse_hex_uint(STRN("00abcdeF01"), &val), 10);
986 1 EXPECT_UINT_EQ(val, 0xABCDEF01);
987
988 1 val = 0x170;
989 1 EXPECT_EQ(buf_parse_hex_uint("0123456789", 4, &val), 4);
990 1 EXPECT_UINT_EQ(val, 0x123);
991 1 }
992
993 1 static void test_str_to_int(TestContext *ctx)
994 {
995 1 int val = 0;
996 1 EXPECT_TRUE(str_to_int("-1", &val));
997 1 EXPECT_EQ(val, -1);
998 1 EXPECT_TRUE(str_to_int("+1", &val));
999 1 EXPECT_EQ(val, 1);
1000 1 EXPECT_TRUE(str_to_int("0", &val));
1001 1 EXPECT_EQ(val, 0);
1002 1 EXPECT_TRUE(str_to_int("1", &val));
1003 1 EXPECT_EQ(val, 1);
1004 1 EXPECT_TRUE(str_to_int("+00299", &val));
1005 1 EXPECT_EQ(val, 299);
1006
1007 1 EXPECT_FALSE(str_to_int("", &val));
1008 1 EXPECT_FALSE(str_to_int("100x", &val));
1009 1 EXPECT_FALSE(str_to_int("+-100", &val));
1010 1 EXPECT_FALSE(str_to_int("99999999999999999999999999999999", &val));
1011 1 }
1012
1013 1 static void test_str_to_size(TestContext *ctx)
1014 {
1015 1 size_t val = 0;
1016 1 EXPECT_TRUE(str_to_size("100", &val));
1017 1 EXPECT_EQ(val, 100);
1018 1 EXPECT_TRUE(str_to_size("0", &val));
1019 1 EXPECT_EQ(val, 0);
1020 1 EXPECT_TRUE(str_to_size("000000001003", &val));
1021 1 EXPECT_EQ(val, 1003);
1022 1 EXPECT_TRUE(str_to_size("29132", &val));
1023 1 EXPECT_EQ(val, 29132);
1024
1025 1 EXPECT_FALSE(str_to_size("", &val));
1026 1 EXPECT_FALSE(str_to_size("100x", &val));
1027 1 EXPECT_FALSE(str_to_size("-100", &val));
1028 1 EXPECT_FALSE(str_to_size("99999999999999999999999999999999", &val));
1029 1 }
1030
1031 1 static void test_str_to_filepos(TestContext *ctx)
1032 {
1033 1 size_t line = 0;
1034 1 size_t col = 0;
1035 1 EXPECT_TRUE(str_to_filepos("10,60", &line, &col));
1036 1 EXPECT_EQ(line, 10);
1037 1 EXPECT_EQ(col, 60);
1038
1039 1 EXPECT_TRUE(str_to_filepos("1:9", &line, &col));
1040 1 EXPECT_EQ(line, 1);
1041 1 EXPECT_EQ(col, 9);
1042
1043 1 EXPECT_TRUE(str_to_filepos("2", &line, &col));
1044 1 EXPECT_EQ(line, 2);
1045 1 EXPECT_EQ(col, 1);
1046
1047 1 EXPECT_TRUE(str_to_filepos("3,1", &line, &col));
1048 1 EXPECT_EQ(line, 3);
1049 1 EXPECT_EQ(col, 1);
1050
1051 1 EXPECT_TRUE(str_to_xfilepos("4", &line, &col));
1052 1 EXPECT_EQ(line, 4);
1053 1 EXPECT_EQ(col, 0);
1054
1055 1 EXPECT_TRUE(str_to_xfilepos("5,1", &line, &col));
1056 1 EXPECT_EQ(line, 5);
1057 1 EXPECT_EQ(col, 1);
1058
1059 1 line = 1111;
1060 1 col = 2222;
1061 1 EXPECT_FALSE(str_to_filepos("0", &line, &col));
1062 1 EXPECT_FALSE(str_to_filepos("1,0", &line, &col));
1063 1 EXPECT_FALSE(str_to_filepos("0,1", &line, &col));
1064 1 EXPECT_FALSE(str_to_filepos("1,2,3", &line, &col));
1065 1 EXPECT_FALSE(str_to_filepos("1,2.3", &line, &col));
1066 1 EXPECT_FALSE(str_to_filepos("5,", &line, &col));
1067 1 EXPECT_FALSE(str_to_filepos(",5", &line, &col));
1068 1 EXPECT_FALSE(str_to_filepos("6.7", &line, &col));
1069 1 EXPECT_FALSE(str_to_filepos("2 3", &line, &col));
1070 1 EXPECT_FALSE(str_to_filepos("9 ", &line, &col));
1071 1 EXPECT_FALSE(str_to_filepos("", &line, &col));
1072 1 EXPECT_FALSE(str_to_filepos("\t", &line, &col));
1073 1 EXPECT_FALSE(str_to_filepos("44,9x", &line, &col));
1074 1 EXPECT_EQ(line, 1111);
1075 1 EXPECT_EQ(col, 2222);
1076 1 }
1077
1078 1 static void test_buf_umax_to_hex_str(TestContext *ctx)
1079 {
1080 1 char buf[HEX_STR_MAX(uintmax_t)];
1081 1 memset(buf, '@', sizeof(buf));
1082
1083 1 size_t ndigits = buf_umax_to_hex_str(0x98EA412F0ull, buf, 0);
1084 1 EXPECT_EQ(ndigits, 9);
1085 1 EXPECT_STREQ(buf, "98EA412F0");
1086
1087 1 ndigits = buf_umax_to_hex_str(0xE, buf, 0);
1088 1 EXPECT_EQ(ndigits, 1);
1089 1 EXPECT_STREQ(buf, "E");
1090
1091 1 ndigits = buf_umax_to_hex_str(0xF, buf, 4);
1092 1 EXPECT_EQ(ndigits, 4);
1093 1 EXPECT_STREQ(buf, "000F");
1094
1095 1 ndigits = buf_umax_to_hex_str(0, buf, 10);
1096 1 EXPECT_EQ(ndigits, 10);
1097 1 EXPECT_STREQ(buf, "0000000000");
1098
1099 1 ndigits = buf_umax_to_hex_str(0xEF1300, buf, 8);
1100 1 EXPECT_EQ(ndigits, 8);
1101 1 EXPECT_STREQ(buf, "00EF1300");
1102
1103 1 ndigits = buf_umax_to_hex_str(0x1000, buf, 3);
1104 1 EXPECT_EQ(ndigits, 4);
1105 1 EXPECT_STREQ(buf, "1000");
1106
1107 1 ndigits = buf_umax_to_hex_str(0, buf, 0);
1108 1 EXPECT_EQ(ndigits, 1);
1109 1 EXPECT_STREQ(buf, "0");
1110
1111 1 ndigits = buf_umax_to_hex_str(1, buf, 0);
1112 1 EXPECT_EQ(ndigits, 1);
1113 1 EXPECT_STREQ(buf, "1");
1114
1115 1 ndigits = buf_umax_to_hex_str(0x10000000ULL, buf, 0);
1116 1 EXPECT_EQ(ndigits, 8);
1117 1 EXPECT_STREQ(buf, "10000000");
1118
1119 1 ndigits = buf_umax_to_hex_str(0x11111111ULL, buf, 0);
1120 1 EXPECT_EQ(ndigits, 8);
1121 1 EXPECT_STREQ(buf, "11111111");
1122
1123 1 ndigits = buf_umax_to_hex_str(0x123456789ABCDEF0ULL, buf, 0);
1124 1 EXPECT_EQ(ndigits, 16);
1125 1 EXPECT_STREQ(buf, "123456789ABCDEF0");
1126
1127 1 ndigits = buf_umax_to_hex_str(0xFFFFFFFFFFFFFFFFULL, buf, 0);
1128 1 EXPECT_EQ(ndigits, 16);
1129 1 EXPECT_STREQ(buf, "FFFFFFFFFFFFFFFF");
1130 1 }
1131
1132 1 static void test_parse_filesize(TestContext *ctx)
1133 {
1134 1 EXPECT_EQ(parse_filesize("0"), 0);
1135 1 EXPECT_EQ(parse_filesize("1"), 1);
1136 1 EXPECT_EQ(parse_filesize("1KiB"), 1024);
1137 1 EXPECT_EQ(parse_filesize("4GiB"), 4LL << 30);
1138 1 EXPECT_EQ(parse_filesize("4096MiB"), 4LL << 30);
1139 1 EXPECT_EQ(parse_filesize("1234567890"), 1234567890LL);
1140 1 EXPECT_EQ(parse_filesize("9GiB"), 9LL << 30);
1141 1 EXPECT_EQ(parse_filesize("1GiB"), 1LL << 30);
1142 1 EXPECT_EQ(parse_filesize("0GiB"), 0);
1143 1 EXPECT_EQ(parse_filesize("0KiB"), 0);
1144 1 EXPECT_EQ(parse_filesize("1MiB"), 1LL << 20);
1145 1 EXPECT_EQ(parse_filesize("1TiB"), 1LL << 40);
1146 1 EXPECT_EQ(parse_filesize("1PiB"), 1LL << 50);
1147 1 EXPECT_EQ(parse_filesize("1EiB"), 1LL << 60);
1148
1149 1 EXPECT_EQ(parse_filesize("4i"), -EINVAL);
1150 1 EXPECT_EQ(parse_filesize("4B"), -EINVAL);
1151 1 EXPECT_EQ(parse_filesize("4GB"), -EINVAL);
1152 1 EXPECT_EQ(parse_filesize("G4"), -EINVAL);
1153 1 EXPECT_EQ(parse_filesize("4G_"), -EINVAL);
1154 1 EXPECT_EQ(parse_filesize(" 4G"), -EINVAL);
1155 1 EXPECT_EQ(parse_filesize("4G "), -EINVAL);
1156 1 EXPECT_EQ(parse_filesize("1K"), -EINVAL);
1157 1 EXPECT_EQ(parse_filesize("4G"), -EINVAL);
1158 1 EXPECT_EQ(parse_filesize("4096M"), -EINVAL);
1159 1 EXPECT_EQ(parse_filesize("9Gi"), -EINVAL);
1160 1 EXPECT_EQ(parse_filesize("0K"), -EINVAL);
1161
1162 1 char buf[DECIMAL_STR_MAX(uintmax_t) + 4];
1163 1 xsnprintf(buf, sizeof buf, "%jd", INTMAX_MAX);
1164 1 EXPECT_EQ(parse_filesize(buf), INTMAX_MAX);
1165 1 xsnprintf(buf, sizeof buf, "%jdKiB", INTMAX_MAX);
1166 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1167 1 xsnprintf(buf, sizeof buf, "%jdEiB", INTMAX_MAX);
1168 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1169 1 xsnprintf(buf, sizeof buf, "%ju", UINTMAX_MAX);
1170 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1171 1 }
1172
1173 1 static void test_umax_to_str(TestContext *ctx)
1174 {
1175 1 EXPECT_STREQ(umax_to_str(0), "0");
1176 1 EXPECT_STREQ(umax_to_str(1), "1");
1177 1 EXPECT_STREQ(umax_to_str(7), "7");
1178 1 EXPECT_STREQ(umax_to_str(99), "99");
1179 1 EXPECT_STREQ(umax_to_str(111), "111");
1180 1 EXPECT_STREQ(umax_to_str(1000), "1000");
1181 1 EXPECT_STREQ(umax_to_str(20998), "20998");
1182
1183 1 uintmax_t x = UINTMAX_MAX;
1184 1 char ref[DECIMAL_STR_MAX(x)];
1185 1 xsnprintf(ref, sizeof ref, "%ju", x);
1186 1 EXPECT_STREQ(umax_to_str(x), ref);
1187 1 x--;
1188 1 xsnprintf(ref, sizeof ref, "%ju", x);
1189 1 EXPECT_STREQ(umax_to_str(x), ref);
1190 1 }
1191
1192 1 static void test_uint_to_str(TestContext *ctx)
1193 {
1194 1 EXPECT_STREQ(uint_to_str(0), "0");
1195 1 EXPECT_STREQ(uint_to_str(1), "1");
1196 1 EXPECT_STREQ(uint_to_str(9), "9");
1197 1 EXPECT_STREQ(uint_to_str(10), "10");
1198 1 EXPECT_STREQ(uint_to_str(11), "11");
1199 1 EXPECT_STREQ(uint_to_str(99), "99");
1200 1 EXPECT_STREQ(uint_to_str(100), "100");
1201 1 EXPECT_STREQ(uint_to_str(101), "101");
1202 1 EXPECT_STREQ(uint_to_str(21904), "21904");
1203
1204 // See test_posix_sanity()
1205 1 static_assert(sizeof(unsigned int) >= 4);
1206 1 static_assert(CHAR_BIT == 8);
1207 1 static_assert(UINT_MAX >= 4294967295u);
1208 1 static_assert(4294967295u == 0xFFFFFFFF);
1209 1 EXPECT_STREQ(uint_to_str(4294967295u), "4294967295");
1210 1 }
1211
1212 1 static void test_ulong_to_str(TestContext *ctx)
1213 {
1214 1 unsigned long x = ULONG_MAX;
1215 1 char ref[DECIMAL_STR_MAX(x)];
1216 1 xsnprintf(ref, sizeof ref, "%lu", x);
1217 1 EXPECT_STREQ(ulong_to_str(x), ref);
1218 1 EXPECT_STREQ(ulong_to_str(x + 1), "0");
1219 1 }
1220
1221 1 static void test_buf_umax_to_str(TestContext *ctx)
1222 {
1223 1 char buf[DECIMAL_STR_MAX(uintmax_t)];
1224 1 EXPECT_EQ(buf_umax_to_str(0, buf), 1);
1225 1 EXPECT_STREQ(buf, "0");
1226 1 EXPECT_EQ(buf_umax_to_str(1, buf), 1);
1227 1 EXPECT_STREQ(buf, "1");
1228 1 EXPECT_EQ(buf_umax_to_str(9, buf), 1);
1229 1 EXPECT_STREQ(buf, "9");
1230 1 EXPECT_EQ(buf_umax_to_str(10, buf), 2);
1231 1 EXPECT_STREQ(buf, "10");
1232 1 EXPECT_EQ(buf_umax_to_str(1234567890ull, buf), 10);
1233 1 EXPECT_STREQ(buf, "1234567890");
1234 1 EXPECT_EQ(buf_umax_to_str(9087654321ull, buf), 10);
1235 1 EXPECT_STREQ(buf, "9087654321");
1236 1 static_assert(sizeof(buf) > 20);
1237 1 EXPECT_EQ(buf_umax_to_str(18446744073709551615ull, buf), 20);
1238 1 EXPECT_STREQ(buf, "18446744073709551615");
1239 1 }
1240
1241 1 static void test_buf_uint_to_str(TestContext *ctx)
1242 {
1243 1 char buf[DECIMAL_STR_MAX(unsigned int)];
1244 1 EXPECT_EQ(buf_uint_to_str(0, buf), 1);
1245 1 EXPECT_STREQ(buf, "0");
1246 1 EXPECT_EQ(buf_uint_to_str(1, buf), 1);
1247 1 EXPECT_STREQ(buf, "1");
1248 1 EXPECT_EQ(buf_uint_to_str(9, buf), 1);
1249 1 EXPECT_STREQ(buf, "9");
1250 1 EXPECT_EQ(buf_uint_to_str(129, buf), 3);
1251 1 EXPECT_STREQ(buf, "129");
1252 1 EXPECT_EQ(buf_uint_to_str(21904, buf), 5);
1253 1 EXPECT_STREQ(buf, "21904");
1254 1 static_assert(sizeof(buf) > 10);
1255 1 EXPECT_EQ(buf_uint_to_str(4294967295u, buf), 10);
1256 1 EXPECT_STREQ(buf, "4294967295");
1257 1 }
1258
1259 1 static void test_buf_u8_to_str(TestContext *ctx)
1260 {
1261 // Note: EXPECT_STREQ() only works here if the tests are done in ascending
1262 // order, since buf_u8_to_str() doesn't null-terminate the buffer
1263 1 char buf[4] = {0};
1264 1 EXPECT_EQ(buf_u8_to_str(0, buf), 1);
1265 1 EXPECT_STREQ(buf, "0");
1266 1 EXPECT_EQ(buf_u8_to_str(1, buf), 1);
1267 1 EXPECT_STREQ(buf, "1");
1268 1 EXPECT_EQ(buf_u8_to_str(9, buf), 1);
1269 1 EXPECT_STREQ(buf, "9");
1270 1 EXPECT_EQ(buf_u8_to_str(99, buf), 2);
1271 1 EXPECT_STREQ(buf, "99");
1272 1 EXPECT_EQ(buf_u8_to_str(100, buf), 3);
1273 1 EXPECT_STREQ(buf, "100");
1274 1 EXPECT_EQ(buf_u8_to_str(255, buf), 3);
1275 1 EXPECT_STREQ(buf, "255");
1276 1 }
1277
1278 1 static void test_file_permissions_to_str(TestContext *ctx)
1279 {
1280 1 char buf[12];
1281 1 EXPECT_STREQ("---------", file_permissions_to_str(0, buf));
1282 1 EXPECT_STREQ("--------x", file_permissions_to_str(01, buf));
1283 1 EXPECT_STREQ("--x--x--x", file_permissions_to_str(0111, buf));
1284 1 EXPECT_STREQ("rwx------", file_permissions_to_str(0700, buf));
1285 1 EXPECT_STREQ("r--r--r--", file_permissions_to_str(0444, buf));
1286 1 EXPECT_STREQ("rw-rw-rw-", file_permissions_to_str(0666, buf));
1287 1 EXPECT_STREQ("rwxrwxrwx", file_permissions_to_str(0777, buf));
1288
1289 1 EXPECT_STREQ("-----S---", file_permissions_to_str(02000, buf));
1290 1 EXPECT_STREQ("-----s---", file_permissions_to_str(02010, buf));
1291 1 EXPECT_STREQ("--S------", file_permissions_to_str(04000, buf));
1292 1 EXPECT_STREQ("--s------", file_permissions_to_str(04100, buf));
1293 1 EXPECT_STREQ("--S--S---", file_permissions_to_str(06000, buf));
1294 1 EXPECT_STREQ("--s--s---", file_permissions_to_str(06110, buf));
1295 1 EXPECT_STREQ("--s--S---", file_permissions_to_str(06100, buf));
1296 1 EXPECT_STREQ("--S--s---", file_permissions_to_str(06010, buf));
1297
1298 #ifdef S_ISVTX
1299 1 EXPECT_STREQ("--S--S--T", file_permissions_to_str(07000, buf));
1300 1 EXPECT_STREQ("--s--s--t", file_permissions_to_str(07111, buf));
1301 1 EXPECT_STREQ("rwsrwsrwt", file_permissions_to_str(07777, buf));
1302 1 EXPECT_STREQ("rwSrwSrwT", file_permissions_to_str(07666, buf));
1303 1 EXPECT_STREQ("------rwt", file_permissions_to_str(01007, buf));
1304 #else
1305 EXPECT_STREQ("--S--S---", file_permissions_to_str(07000, buf));
1306 EXPECT_STREQ("--s--s--x", file_permissions_to_str(07111, buf));
1307 EXPECT_STREQ("rwsrwsrwx", file_permissions_to_str(07777, buf));
1308 EXPECT_STREQ("rwSrwSrw-", file_permissions_to_str(07666, buf));
1309 EXPECT_STREQ("------rwx", file_permissions_to_str(01007, buf));
1310 #endif
1311 1 }
1312
1313 1 static void test_human_readable_size(TestContext *ctx)
1314 {
1315 1 char buf[HRSIZE_MAX];
1316 1 EXPECT_STREQ(human_readable_size(0, buf), "0");
1317 1 EXPECT_STREQ(human_readable_size(1, buf), "1");
1318 1 EXPECT_STREQ(human_readable_size(10, buf), "10");
1319 1 EXPECT_STREQ(human_readable_size(1u << 10, buf), "1 KiB");
1320 1 EXPECT_STREQ(human_readable_size(4u << 10, buf), "4 KiB");
1321 1 EXPECT_STREQ(human_readable_size(9u << 20, buf), "9 MiB");
1322 1 EXPECT_STREQ(human_readable_size(1024u << 10, buf), "1 MiB");
1323 1 EXPECT_STREQ(human_readable_size(1024u << 20, buf), "1 GiB");
1324 1 EXPECT_STREQ(human_readable_size(1023u << 10, buf), "1023 KiB");
1325 1 EXPECT_STREQ(human_readable_size(1023u << 20, buf), "1023 MiB");
1326 1 EXPECT_STREQ(human_readable_size(900ull << 30, buf), "900 GiB");
1327 1 EXPECT_STREQ(human_readable_size(1ull << 62, buf), "4 EiB");
1328 1 EXPECT_STREQ(human_readable_size((1ull << 62) + 232ull, buf), "4 EiB");
1329 1 EXPECT_STREQ(human_readable_size(3ull << 61, buf), "6 EiB");
1330 1 EXPECT_STREQ(human_readable_size(11ull << 59, buf), "5.50 EiB");
1331
1332 // Compare to e.g.: numfmt --to=iec --format=%0.7f 7427273
1333 1 EXPECT_STREQ(human_readable_size(990, buf), "990");
1334 1 EXPECT_STREQ(human_readable_size(1023, buf), "1023");
1335 1 EXPECT_STREQ(human_readable_size(1025, buf), "1 KiB");
1336 1 EXPECT_STREQ(human_readable_size(1123, buf), "1.09 KiB");
1337 1 EXPECT_STREQ(human_readable_size(1124, buf), "1.10 KiB");
1338 1 EXPECT_STREQ(human_readable_size(1127, buf), "1.10 KiB");
1339 1 EXPECT_STREQ(human_readable_size(4106, buf), "4.01 KiB");
1340 1 EXPECT_STREQ(human_readable_size(4192, buf), "4.09 KiB");
1341 1 EXPECT_STREQ(human_readable_size(4195, buf), "4.09 KiB");
1342 1 EXPECT_STREQ(human_readable_size(4196, buf), "4.10 KiB");
1343 1 EXPECT_STREQ(human_readable_size(4197, buf), "4.10 KiB");
1344 1 EXPECT_STREQ(human_readable_size(6947713, buf), "6.62 MiB");
1345 1 EXPECT_STREQ(human_readable_size(7427273, buf), "7.08 MiB");
1346 1 EXPECT_STREQ(human_readable_size(1116691500ull, buf), "1.04 GiB");
1347 1 EXPECT_STREQ(human_readable_size(8951980327583ull, buf), "8.14 TiB");
1348 1 EXPECT_STREQ(human_readable_size(8951998035275183ull, buf), "7.95 PiB");
1349
1350 // Some of these results are arguably off by 0.01, but that's fine
1351 // given the approximate nature of the function and its use cases.
1352 // These tests are here mostly to exercise edge cases and provide
1353 // useful feedback when tweaking the algorithm.
1354 1 EXPECT_STREQ(human_readable_size(5242803, buf), "4.99 MiB");
1355 1 EXPECT_STREQ(human_readable_size(5242804, buf), "5 MiB");
1356 1 EXPECT_STREQ(human_readable_size(5242879, buf), "5 MiB");
1357 1 EXPECT_STREQ(human_readable_size(5242880, buf), "5 MiB");
1358 1 EXPECT_STREQ(human_readable_size(5242881, buf), "5 MiB");
1359
1360 // Compare with e.g. `units '0xFF00000000000000 bytes' EiB`
1361 1 EXPECT_STREQ(human_readable_size(0xFFFFFFFFFFFFFFFFull, buf), "16 EiB");
1362 1 EXPECT_STREQ(human_readable_size(0x7FFFFFFFFFFFFFFFull, buf), "8 EiB");
1363 1 EXPECT_STREQ(human_readable_size(0x3FFFFFFFFFFFFFFFull, buf), "4 EiB");
1364 1 EXPECT_STREQ(human_readable_size(0xFF00000000000000ull, buf), "15.93 EiB");
1365
1366 1 const uintmax_t u64pow2max = 0x8000000000000000ull;
1367 1 EXPECT_STREQ(human_readable_size(u64pow2max, buf), "8 EiB");
1368 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 1), buf), "12 EiB");
1369 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 2), buf), "10 EiB");
1370 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 3), buf), "9 EiB");
1371 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 4), buf), "8.50 EiB");
1372 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 5), buf), "8.25 EiB");
1373 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 6), buf), "8.12 EiB");
1374 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 7), buf), "8.06 EiB");
1375 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 8), buf), "8.03 EiB");
1376 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 9), buf), "8.01 EiB");
1377 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 10), buf), "8 EiB");
1378 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 11), buf), "8 EiB");
1379 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1, buf), "4 EiB");
1380 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 2, buf), "2 EiB");
1381 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 3, buf), "1 EiB");
1382 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 4, buf), "512 PiB");
1383 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 2), buf), "6 EiB");
1384 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 3), buf), "5 EiB");
1385 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 4), buf), "4.50 EiB");
1386 1 }
1387
1388 1 static void test_filesize_to_str(TestContext *ctx)
1389 {
1390 1 char buf[FILESIZE_STR_MAX];
1391 1 EXPECT_STREQ(filesize_to_str(0, buf), "0");
1392 1 EXPECT_STREQ(filesize_to_str(1023, buf), "1023");
1393 1 EXPECT_STREQ(filesize_to_str(1024, buf), "1 KiB (1024)");
1394
1395 1 static_assert(18446744073709551615ull == 0xFFFFFFFFFFFFFFFFull);
1396 1 EXPECT_STREQ(filesize_to_str(18446744073709551615ull, buf), "16 EiB (18446744073709551615)");
1397 1 EXPECT_STREQ(filesize_to_str(17446744073709551615ull, buf), "15.13 EiB (17446744073709551615)");
1398 1 }
1399
1400 1 static void test_u_char_size(TestContext *ctx)
1401 {
1402 1 EXPECT_EQ(u_char_size('\0'), 1);
1403 1 EXPECT_EQ(u_char_size(' '), 1);
1404 1 EXPECT_EQ(u_char_size('z'), 1);
1405 1 EXPECT_EQ(u_char_size(0x7E), 1);
1406 1 EXPECT_EQ(u_char_size(0x7F), 1);
1407 1 EXPECT_EQ(u_char_size(0x80), 2);
1408 1 EXPECT_EQ(u_char_size(0x81), 2);
1409 1 EXPECT_EQ(u_char_size(0xFF), 2);
1410 1 EXPECT_EQ(u_char_size(0x7FE), 2);
1411 1 EXPECT_EQ(u_char_size(0x7FF), 2);
1412 1 EXPECT_EQ(u_char_size(0x800), 3);
1413 1 EXPECT_EQ(u_char_size(0x801), 3);
1414 1 EXPECT_EQ(u_char_size(0x1234), 3);
1415 1 EXPECT_EQ(u_char_size(0xFFFE), 3);
1416 1 EXPECT_EQ(u_char_size(0xFFFF), 3);
1417 1 EXPECT_EQ(u_char_size(0x10000), 4);
1418 1 EXPECT_EQ(u_char_size(0x10001), 4);
1419 1 EXPECT_EQ(u_char_size(0x10FFFE), 4);
1420 1 EXPECT_EQ(u_char_size(0x10FFFF), 4);
1421 1 EXPECT_EQ(u_char_size(0x110000), 1);
1422 1 EXPECT_EQ(u_char_size(0x110001), 1);
1423 1 EXPECT_EQ(u_char_size(UINT32_MAX), 1);
1424 1 }
1425
1426 1 static void test_u_char_width(TestContext *ctx)
1427 {
1428 // ASCII (1 column)
1429 1 EXPECT_EQ(u_char_width('a'), 1);
1430 1 EXPECT_EQ(u_char_width('z'), 1);
1431 1 EXPECT_EQ(u_char_width('A'), 1);
1432 1 EXPECT_EQ(u_char_width('Z'), 1);
1433 1 EXPECT_EQ(u_char_width(' '), 1);
1434 1 EXPECT_EQ(u_char_width('!'), 1);
1435 1 EXPECT_EQ(u_char_width('/'), 1);
1436 1 EXPECT_EQ(u_char_width('^'), 1);
1437 1 EXPECT_EQ(u_char_width('`'), 1);
1438 1 EXPECT_EQ(u_char_width('~'), 1);
1439
1440 // Rendered in caret notation (2 columns)
1441 1 EXPECT_EQ(u_char_width('\0'), 2);
1442 1 EXPECT_EQ(u_char_width('\t'), 2);
1443 1 EXPECT_EQ(u_char_width('\n'), 2);
1444 1 EXPECT_EQ(u_char_width('\r'), 2);
1445 1 EXPECT_EQ(u_char_width(0x1F), 2);
1446 1 EXPECT_EQ(u_char_width(0x7F), 2);
1447
1448 // Unprintable (rendered as <xx> -- 4 columns)
1449 1 EXPECT_EQ(u_char_width(0x0080), 4);
1450 1 EXPECT_EQ(u_char_width(0xDFFF), 4);
1451
1452 // Zero width (0 columns)
1453 1 EXPECT_EQ(u_char_width(0xAA31), 0);
1454 1 EXPECT_EQ(u_char_width(0xAA32), 0);
1455
1456 // Double width (2 columns)
1457 1 EXPECT_EQ(u_char_width(0x2757), 2);
1458 1 EXPECT_EQ(u_char_width(0x312F), 2);
1459 1 EXPECT_EQ(u_char_width(0x30000), 2);
1460
1461 // Double width but unassigned (rendered as <xx> -- 4 columns)
1462 1 EXPECT_EQ(u_char_width(0x3A009), 4);
1463 1 EXPECT_EQ(u_char_width(0x3FFFD), 4);
1464
1465 // 1 column character >= 0x1100
1466 1 EXPECT_EQ(u_char_width(0x104B3), 1);
1467 1 }
1468
1469 1 static void test_u_to_lower(TestContext *ctx)
1470 {
1471 1 EXPECT_EQ(u_to_lower('A'), 'a');
1472 1 EXPECT_EQ(u_to_lower('Z'), 'z');
1473 1 EXPECT_EQ(u_to_lower('a'), 'a');
1474 1 EXPECT_EQ(u_to_lower('0'), '0');
1475 1 EXPECT_EQ(u_to_lower('~'), '~');
1476 1 EXPECT_EQ(u_to_lower('@'), '@');
1477 1 EXPECT_EQ(u_to_lower('\0'), '\0');
1478 1 }
1479
1480 1 static void test_u_to_upper(TestContext *ctx)
1481 {
1482 1 EXPECT_EQ(u_to_upper('a'), 'A');
1483 1 EXPECT_EQ(u_to_upper('z'), 'Z');
1484 1 EXPECT_EQ(u_to_upper('A'), 'A');
1485 1 EXPECT_EQ(u_to_upper('0'), '0');
1486 1 EXPECT_EQ(u_to_upper('~'), '~');
1487 1 EXPECT_EQ(u_to_upper('@'), '@');
1488 1 EXPECT_EQ(u_to_upper('\0'), '\0');
1489 1 }
1490
1491 1 static void test_u_is_lower(TestContext *ctx)
1492 {
1493 1 EXPECT_TRUE(u_is_lower('a'));
1494 1 EXPECT_TRUE(u_is_lower('z'));
1495 1 EXPECT_FALSE(u_is_lower('A'));
1496 1 EXPECT_FALSE(u_is_lower('Z'));
1497 1 EXPECT_FALSE(u_is_lower('0'));
1498 1 EXPECT_FALSE(u_is_lower('9'));
1499 1 EXPECT_FALSE(u_is_lower('@'));
1500 1 EXPECT_FALSE(u_is_lower('['));
1501 1 EXPECT_FALSE(u_is_lower('{'));
1502 1 EXPECT_FALSE(u_is_lower('\0'));
1503 1 EXPECT_FALSE(u_is_lower('\t'));
1504 1 EXPECT_FALSE(u_is_lower(' '));
1505 1 EXPECT_FALSE(u_is_lower(0x1F315));
1506 1 EXPECT_FALSE(u_is_lower(0x10ffff));
1507
1508 /*
1509 Even if SANE_WCTYPE is defined, we still can't make many assumptions
1510 about the iswlower(3) implementation, since it depends on all kinds
1511 of factors out of our control. Otherwise it'd be reasonable to test
1512 something like:
1513
1514 EXPECT_TRUE(u_is_lower(0x00E0));
1515 EXPECT_TRUE(u_is_lower(0x00E7));
1516 */
1517 1 }
1518
1519 1 static void test_u_is_upper(TestContext *ctx)
1520 {
1521 1 EXPECT_TRUE(u_is_upper('A'));
1522 1 EXPECT_TRUE(u_is_upper('Z'));
1523 1 EXPECT_FALSE(u_is_upper('a'));
1524 1 EXPECT_FALSE(u_is_upper('z'));
1525 1 EXPECT_FALSE(u_is_upper('0'));
1526 1 EXPECT_FALSE(u_is_upper('9'));
1527 1 EXPECT_FALSE(u_is_upper('@'));
1528 1 EXPECT_FALSE(u_is_upper('['));
1529 1 EXPECT_FALSE(u_is_upper('{'));
1530 1 EXPECT_FALSE(u_is_upper('\0'));
1531 1 EXPECT_FALSE(u_is_upper('\t'));
1532 1 EXPECT_FALSE(u_is_upper(' '));
1533 1 EXPECT_FALSE(u_is_upper(0x1F315));
1534 1 EXPECT_FALSE(u_is_upper(0x10ffff));
1535 1 EXPECT_FALSE(u_is_upper(0x00E0));
1536 1 EXPECT_FALSE(u_is_upper(0x00E7));
1537 1 }
1538
1539 1 static void test_u_is_ascii_upper(TestContext *ctx)
1540 {
1541 1 EXPECT_TRUE(u_is_ascii_upper('A'));
1542 1 EXPECT_TRUE(u_is_ascii_upper('Z'));
1543 1 EXPECT_FALSE(u_is_ascii_upper('a'));
1544 1 EXPECT_FALSE(u_is_ascii_upper('z'));
1545 1 EXPECT_FALSE(u_is_ascii_upper('0'));
1546 1 EXPECT_FALSE(u_is_ascii_upper('9'));
1547 1 EXPECT_FALSE(u_is_ascii_upper('@'));
1548 1 EXPECT_FALSE(u_is_ascii_upper('['));
1549 1 EXPECT_FALSE(u_is_ascii_upper('{'));
1550 1 EXPECT_FALSE(u_is_ascii_upper('\0'));
1551 1 EXPECT_FALSE(u_is_ascii_upper('\t'));
1552 1 EXPECT_FALSE(u_is_ascii_upper(' '));
1553 1 EXPECT_FALSE(u_is_ascii_upper(0x7F));
1554 1 EXPECT_FALSE(u_is_ascii_upper(0x1D440));
1555 1 EXPECT_FALSE(u_is_ascii_upper(UNICODE_MAX_VALID_CODEPOINT));
1556 1 }
1557
1558 1 static void test_u_is_cntrl(TestContext *ctx)
1559 {
1560 1 EXPECT_TRUE(u_is_cntrl(0x00));
1561 1 EXPECT_TRUE(u_is_cntrl(0x09));
1562 1 EXPECT_TRUE(u_is_cntrl(0x0D));
1563 1 EXPECT_TRUE(u_is_cntrl(0x1F));
1564 1 EXPECT_TRUE(u_is_cntrl(0x7F));
1565 1 EXPECT_TRUE(u_is_cntrl(0x80));
1566 1 EXPECT_TRUE(u_is_cntrl(0x81));
1567 1 EXPECT_TRUE(u_is_cntrl(0x9E));
1568 1 EXPECT_TRUE(u_is_cntrl(0x9F));
1569 1 EXPECT_FALSE(u_is_cntrl(0x20));
1570 1 EXPECT_FALSE(u_is_cntrl(0x21));
1571 1 EXPECT_FALSE(u_is_cntrl(0x7E));
1572 1 EXPECT_FALSE(u_is_cntrl(0xA0));
1573 1 EXPECT_FALSE(u_is_cntrl(0x41));
1574 1 EXPECT_FALSE(u_is_cntrl(0x61));
1575 1 EXPECT_FALSE(u_is_cntrl(0xFF));
1576 1 }
1577
1578 1 static void test_u_is_zero_width(TestContext *ctx)
1579 {
1580 // Default ignorable codepoints:
1581 1 EXPECT_TRUE(u_is_zero_width(0x034F));
1582 1 EXPECT_TRUE(u_is_zero_width(0x061C));
1583 1 EXPECT_TRUE(u_is_zero_width(0x115F));
1584 1 EXPECT_TRUE(u_is_zero_width(0x1160));
1585 1 EXPECT_TRUE(u_is_zero_width(0x180B));
1586 1 EXPECT_TRUE(u_is_zero_width(0x200B));
1587 1 EXPECT_TRUE(u_is_zero_width(0x202E));
1588 1 EXPECT_TRUE(u_is_zero_width(0xFEFF));
1589 1 EXPECT_TRUE(u_is_zero_width(0xE0000));
1590 1 EXPECT_TRUE(u_is_zero_width(0xE0FFF));
1591 // Non-spacing marks:
1592 1 EXPECT_TRUE(u_is_zero_width(0x0300));
1593 1 EXPECT_TRUE(u_is_zero_width(0x0730));
1594 1 EXPECT_TRUE(u_is_zero_width(0x11839));
1595 1 EXPECT_TRUE(u_is_zero_width(0x1183A));
1596 1 EXPECT_TRUE(u_is_zero_width(0xE01EF));
1597 // Not zero-width:
1598 1 EXPECT_FALSE(u_is_zero_width(0x0000));
1599 1 EXPECT_FALSE(u_is_zero_width('Z'));
1600 1 }
1601
1602 1 static void test_u_is_special_whitespace(TestContext *ctx)
1603 {
1604 1 EXPECT_FALSE(u_is_special_whitespace(' '));
1605 1 EXPECT_FALSE(u_is_special_whitespace('\t'));
1606 1 EXPECT_FALSE(u_is_special_whitespace('\n'));
1607 1 EXPECT_FALSE(u_is_special_whitespace('a'));
1608 1 EXPECT_FALSE(u_is_special_whitespace(0x1680));
1609 1 EXPECT_FALSE(u_is_special_whitespace(0x3000));
1610 1 EXPECT_TRUE(u_is_special_whitespace(0x00A0));
1611 1 EXPECT_TRUE(u_is_special_whitespace(0x00AD));
1612 1 EXPECT_TRUE(u_is_special_whitespace(0x2000));
1613 1 EXPECT_TRUE(u_is_special_whitespace(0x200a));
1614 1 EXPECT_TRUE(u_is_special_whitespace(0x2028));
1615 1 EXPECT_TRUE(u_is_special_whitespace(0x2029));
1616 1 EXPECT_TRUE(u_is_special_whitespace(0x202f));
1617 1 EXPECT_TRUE(u_is_special_whitespace(0x205f));
1618 1 }
1619
1620 1 static void test_u_is_unprintable(TestContext *ctx)
1621 {
1622 // Private-use characters ------------------------------------------
1623 // (https://www.unicode.org/faq/private_use.html#pua2)
1624
1625 // There are three ranges of private-use characters in the standard.
1626 // The main range in the BMP is U+E000..U+F8FF, containing 6,400
1627 // private-use characters.
1628 1 EXPECT_FALSE(u_is_unprintable(0xE000));
1629 1 EXPECT_FALSE(u_is_unprintable(0xF8FF));
1630
1631 // ... there are also two large ranges of supplementary private-use
1632 // characters, consisting of most of the code points on planes 15
1633 // and 16: U+F0000..U+FFFFD and U+100000..U+10FFFD. Together those
1634 // ranges allocate another 131,068 private-use characters.
1635 1 EXPECT_FALSE(u_is_unprintable(0xF0000));
1636 1 EXPECT_FALSE(u_is_unprintable(0xFFFFD));
1637 1 EXPECT_FALSE(u_is_unprintable(0x100000));
1638 1 EXPECT_FALSE(u_is_unprintable(0x10FFFD));
1639
1640 // Non-characters --------------------------------------------------
1641 // (https://www.unicode.org/faq/private_use.html#noncharacters)
1642 1 unsigned int noncharacter_count = 0;
1643
1644 // "A contiguous range of 32 noncharacters: U+FDD0..U+FDEF in the BMP"
1645
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 for (CodePoint u = 0xFDD0; u <= 0xFDEF; u++) {
1646 32 EXPECT_TRUE(u_is_unprintable(u));
1647 32 noncharacter_count++;
1648 }
1649
1650 // "The last two code points of the BMP, U+FFFE and U+FFFF"
1651 1 EXPECT_TRUE(u_is_unprintable(0xFFFE));
1652 1 EXPECT_TRUE(u_is_unprintable(0xFFFF));
1653 1 noncharacter_count += 2;
1654
1655 // "The last two code points of each of the 16 supplementary planes:
1656 // U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, ... U+10FFFE, U+10FFFF"
1657
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
17 for (CodePoint step = 1; step <= 16; step++) {
1658 16 const CodePoint u = (0x10000 * step) + 0xFFFE;
1659 16 EXPECT_TRUE(u_is_unprintable(u));
1660 16 EXPECT_TRUE(u_is_unprintable(u + 1));
1661 16 noncharacter_count += 2;
1662 }
1663
1664 // "Q: How many noncharacters does Unicode have?"
1665 // "A: Exactly 66"
1666 1 EXPECT_EQ(noncharacter_count, 66);
1667 1 }
1668
1669 1 static void test_u_str_width(TestContext *ctx)
1670 {
1671 1 EXPECT_EQ(u_str_width("foo"), 3);
1672 1 EXPECT_EQ (
1673 7, u_str_width (
1674 "\xE0\xB8\x81\xE0\xB8\xB3\xE0\xB9\x81\xE0\xB8\x9E\xE0\xB8"
1675 "\x87\xE0\xB8\xA1\xE0\xB8\xB5\xE0\xB8\xAB\xE0\xB8\xB9"
1676 )
1677 );
1678 1 }
1679
1680 1 static void test_u_set_char_raw(TestContext *ctx)
1681 {
1682 1 unsigned char buf[UTF8_MAX_SEQ_LEN] = "";
1683 1 EXPECT_EQ(sizeof(buf), 4);
1684 1 EXPECT_EQ(u_set_char_raw(buf, 'a'), 1);
1685 1 EXPECT_EQ(buf[0], 'a');
1686
1687 1 EXPECT_EQ(u_set_char_raw(buf, '\0'), 1);
1688 1 EXPECT_EQ(buf[0], '\0');
1689
1690 1 EXPECT_EQ(u_set_char_raw(buf, 0x1F), 1);
1691 1 EXPECT_EQ(buf[0], 0x1F);
1692
1693 1 EXPECT_EQ(u_set_char_raw(buf, 0x7F), 1);
1694 1 EXPECT_EQ(buf[0], 0x7F);
1695
1696 1 EXPECT_EQ(u_set_char_raw(buf, 0x7FF), 2);
1697 1 EXPECT_EQ(buf[0], 0xDF);
1698 1 EXPECT_EQ(buf[1], 0xBF);
1699
1700 1 EXPECT_EQ(u_set_char_raw(buf, 0xFF45), 3);
1701 1 EXPECT_EQ(buf[0], 0xEF);
1702 1 EXPECT_EQ(buf[1], 0xBD);
1703 1 EXPECT_EQ(buf[2], 0x85);
1704
1705 1 EXPECT_EQ(u_set_char_raw(buf, 0x1F311), 4);
1706 1 EXPECT_EQ(buf[0], 0xF0);
1707 1 EXPECT_EQ(buf[1], 0x9F);
1708 1 EXPECT_EQ(buf[2], 0x8C);
1709 1 EXPECT_EQ(buf[3], 0x91);
1710
1711 1 buf[1] = 0x88;
1712 1 EXPECT_EQ(u_set_char_raw(buf, 0x110000), 1);
1713 1 EXPECT_EQ(buf[0], 0);
1714 1 EXPECT_EQ(buf[1], 0x88);
1715
1716 1 EXPECT_EQ(u_set_char_raw(buf, 0x110042), 1);
1717 1 EXPECT_EQ(buf[0], 0x42);
1718 1 EXPECT_EQ(buf[1], 0x88);
1719 1 }
1720
1721 1 static void test_u_set_char(TestContext *ctx)
1722 {
1723 1 unsigned char buf[U_SET_CHAR_MAXLEN] = "";
1724 1 EXPECT_EQ(sizeof(buf), 4);
1725 1 EXPECT_EQ(u_set_char(buf, 'a'), 1);
1726 1 EXPECT_EQ(buf[0], 'a');
1727
1728 1 EXPECT_EQ(u_set_char(buf, 0x00DF), 2);
1729 1 EXPECT_EQ(buf[0], 0xC3);
1730 1 EXPECT_EQ(buf[1], 0x9F);
1731
1732 1 EXPECT_EQ(u_set_char(buf, 0x0E01), 3);
1733 1 EXPECT_EQ(buf[0], 0xE0);
1734 1 EXPECT_EQ(buf[1], 0xB8);
1735 1 EXPECT_EQ(buf[2], 0x81);
1736
1737 1 EXPECT_EQ(UTF8_MAX_SEQ_LEN, 4);
1738 1 EXPECT_EQ(u_set_char(buf, 0x1F914), 4);
1739 1 EXPECT_EQ(buf[0], 0xF0);
1740 1 EXPECT_EQ(buf[1], 0x9F);
1741 1 EXPECT_EQ(buf[2], 0xA4);
1742 1 EXPECT_EQ(buf[3], 0x94);
1743
1744 1 EXPECT_EQ(U_SET_HEX_LEN, 4);
1745 1 EXPECT_EQ(u_set_char(buf, 0x10FFFF), 4);
1746 1 EXPECT_EQ(buf[0], '<');
1747 1 EXPECT_EQ(buf[1], '?');
1748 1 EXPECT_EQ(buf[2], '?');
1749 1 EXPECT_EQ(buf[3], '>');
1750
1751 1 EXPECT_EQ(u_set_char(buf, '\0'), 2);
1752 1 EXPECT_EQ(buf[0], '^');
1753 1 EXPECT_EQ(buf[1], '@');
1754
1755 1 EXPECT_EQ(u_set_char(buf, '\t'), 2);
1756 1 EXPECT_EQ(buf[0], '^');
1757 1 EXPECT_EQ(buf[1], 'I');
1758
1759 1 EXPECT_EQ(u_set_char(buf, 0x1F), 2);
1760 1 EXPECT_EQ(buf[0], '^');
1761 1 EXPECT_EQ(buf[1], '_');
1762
1763 1 EXPECT_EQ(u_set_char(buf, 0x7F), 2);
1764 1 EXPECT_EQ(buf[0], '^');
1765 1 EXPECT_EQ(buf[1], '?');
1766
1767 1 EXPECT_EQ(u_set_char(buf, 0x80), 4);
1768 1 EXPECT_EQ(buf[0], '<');
1769 1 EXPECT_EQ(buf[1], '?');
1770 1 EXPECT_EQ(buf[2], '?');
1771 1 EXPECT_EQ(buf[3], '>');
1772
1773 1 EXPECT_EQ(u_set_char(buf, 0x7E), 1);
1774 1 EXPECT_EQ(buf[0], '~');
1775
1776 1 EXPECT_EQ(u_set_char(buf, 0x20), 1);
1777 1 EXPECT_EQ(buf[0], ' ');
1778
1779 1 unsigned char c = 0xA5;
1780 1 EXPECT_EQ(u_set_char(buf, 0x110000 + c), 4);
1781 1 EXPECT_EQ(buf[0], '<');
1782 1 EXPECT_EQ(buf[1], '5');
1783 1 EXPECT_EQ(buf[2], 'b');
1784 1 EXPECT_EQ(buf[3], '>');
1785 1 c = -c;
1786 1 EXPECT_UINT_EQ(c, 0x5b);
1787 1 }
1788
1789 1 static void test_u_make_printable(TestContext *ctx)
1790 {
1791 1 char buf[5];
1792 1 MakePrintableFlags flags = 0;
1793 1 EXPECT_EQ(sizeof(buf), U_SET_CHAR_MAXLEN + 1);
1794 1 memset(buf, '_', sizeof(buf));
1795 1 EXPECT_EQ(u_make_printable(STRN("\xffxyz"), buf, sizeof(buf), flags), 4);
1796 1 EXPECT_STREQ(buf, "<ff>");
1797
1798 // Enough space for `U_SET_CHAR_MAXLEN + 1` is needed, regardless of
1799 // the CodePoint encountered, so 5 is the minimum remaining space
1800 // required in order to write more than just a null-terminator
1801 1 memset(buf, '_', sizeof(buf));
1802 1 EXPECT_TRUE(sizeof(buf) >= 5);
1803 1 EXPECT_EQ(u_make_printable(STRN("12345"), buf, 1, flags), 0);
1804 1 EXPECT_EQ(u_make_printable(STRN("12345"), buf, 2, flags), 0);
1805 1 EXPECT_EQ(u_make_printable(STRN("12345"), buf, 3, flags), 0);
1806 1 EXPECT_EQ(u_make_printable(STRN("12345"), buf, 4, flags), 0);
1807 1 EXPECT_EQ(buf[0], '\0');
1808 1 EXPECT_EQ(buf[1], '_');
1809 1 EXPECT_EQ(buf[2], '_');
1810 1 EXPECT_EQ(buf[3], '_');
1811 1 EXPECT_EQ(buf[4], '_');
1812 1 memset(buf, '_', sizeof(buf));
1813 1 EXPECT_EQ(u_make_printable(STRN("12345"), buf, 5, flags), 1);
1814 1 EXPECT_EQ(buf[0], '1');
1815 1 EXPECT_EQ(buf[1], '\0');
1816 1 EXPECT_EQ(buf[2], '_');
1817 1 EXPECT_EQ(buf[3], '_');
1818 1 EXPECT_EQ(buf[4], '_');
1819
1820 1 memset(buf, '_', sizeof(buf));
1821 1 EXPECT_EQ(u_make_printable(STRN("\x7F\n123"), buf, 5, flags), 2);
1822 1 EXPECT_STREQ(buf, "^?");
1823 1 EXPECT_EQ(buf[3], '_');
1824
1825 1 flags |= MPF_C0_SYMBOLS;
1826 1 memset(buf, '_', sizeof(buf));
1827 1 EXPECT_EQ(u_make_printable(STRN("\x7F\n123"), buf, 5, flags), 3);
1828 1 EXPECT_STREQ(buf, "\xE2\x90\xA1"); // UTF-8 encoding of U+2421
1829 1 EXPECT_EQ(buf[4], '_');
1830
1831 1 memset(buf, '_', sizeof(buf));
1832 1 EXPECT_EQ(u_make_printable(STRN("\0xyz"), buf, 5, flags), 3);
1833 1 EXPECT_STREQ(buf, "\xE2\x90\x80"); // UTF-8 encoding of U+2400
1834 1 EXPECT_EQ(buf[4], '_');
1835 1 }
1836
1837 1 static void test_u_get_char(TestContext *ctx)
1838 {
1839 1 static const char a[] = "//";
1840 1 size_t idx = 0;
1841 1 EXPECT_EQ(u_get_char(a, sizeof(a), &idx), '/');
1842 1 ASSERT_EQ(idx, 1);
1843 1 EXPECT_EQ(u_get_char(a, sizeof(a), &idx), '/');
1844 1 ASSERT_EQ(idx, 2);
1845 1 EXPECT_EQ(u_get_char(a, sizeof(a), &idx), 0);
1846 1 ASSERT_EQ(idx, 3);
1847
1848 // "In UTF-8, the code point sequence <004D, 0430, 4E8C, 10302> is
1849 // represented as <4D D0 B0 E4 BA 8C F0 90 8C 82>, where <4D>
1850 // corresponds to U+004D, <D0 B0> corresponds to U+0430, <E4 BA 8C>
1851 // corresponds to U+4E8C, and <F0 90 8C 82> corresponds to U+10302."
1852 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G31703
1853 1 static const char b[] = "\x4D\xD0\xB0\xE4\xBA\x8C\xF0\x90\x8C\x82";
1854 1 idx = 0;
1855 1 EXPECT_EQ(u_get_char(b, sizeof b, &idx), 0x004D);
1856 1 ASSERT_EQ(idx, 1);
1857 1 EXPECT_EQ(u_get_char(b, sizeof b, &idx), 0x0430);
1858 1 ASSERT_EQ(idx, 3);
1859 1 EXPECT_EQ(u_get_char(b, sizeof b, &idx), 0x4E8C);
1860 1 ASSERT_EQ(idx, 6);
1861 1 EXPECT_EQ(u_get_char(b, sizeof b, &idx), 0x10302);
1862 1 ASSERT_EQ(idx, 10);
1863
1864 // "The byte sequence <F4 80 83 92> is well-formed, because every
1865 // byte in that sequence matches a byte range in a row of the table
1866 // (the last row)."
1867 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G27288
1868 1 idx = 0;
1869 1 EXPECT_EQ(u_get_char(STRN("\xF4\x80\x83\x92"), &idx), 0x1000D2);
1870 1 EXPECT_EQ(idx, 4);
1871
1872 // Overlong encodings are consumed as individual bytes and
1873 // each byte returned negated (to indicate that it's invalid).
1874 // See also: u_get_nonascii(), u_seq_len_ok(), u_char_size()
1875
1876 // Overlong (2 byte) encoding of U+002F ('/').
1877 // "The byte sequence <C0 AF> is ill-formed, because C0 is not
1878 // well-formed in the “First Byte” column."
1879 1 static const char ol1[] = "\xC0\xAF";
1880 1 idx = 0;
1881 1 EXPECT_EQ(u_get_char(ol1, 2, &idx), (CodePoint)-0xC0);
1882 1 ASSERT_EQ(idx, 1);
1883 1 EXPECT_EQ(u_get_char(ol1, 2, &idx), (CodePoint)-0xAF);
1884 1 ASSERT_EQ(idx, 2);
1885
1886 // Overlong (3 byte) encoding of U+002F ('/')
1887 1 static const char ol2[] = "\xE0\x80\xAF";
1888 1 idx = 0;
1889 1 EXPECT_EQ(u_get_char(ol2, 3, &idx), (CodePoint)-0xE0);
1890 1 ASSERT_EQ(idx, 1);
1891 1 EXPECT_EQ(u_get_char(ol2, 3, &idx), (CodePoint)-0x80);
1892 1 ASSERT_EQ(idx, 2);
1893 1 EXPECT_EQ(u_get_char(ol2, 3, &idx), (CodePoint)-0xAF);
1894 1 ASSERT_EQ(idx, 3);
1895
1896 // "The byte sequence <E0 9F 80> is ill-formed, because in the row
1897 // where E0 is well-formed as a first byte, 9F is not well-formed
1898 // as a second byte."
1899 1 static const char ol3[] = "\xE0\x9F\x80";
1900 1 idx = 0;
1901 1 EXPECT_EQ(u_get_char(ol3, 3, &idx), (CodePoint)-0xE0);
1902 1 ASSERT_EQ(idx, 1);
1903 1 EXPECT_EQ(u_get_char(ol3, 3, &idx), (CodePoint)-0x9F);
1904 1 ASSERT_EQ(idx, 2);
1905 1 EXPECT_EQ(u_get_char(ol3, 3, &idx), (CodePoint)-0x80);
1906 1 ASSERT_EQ(idx, 3);
1907
1908 // "For example, in processing the UTF-8 code unit sequence
1909 // <F0 80 80 41>, the only formal requirement mandated by Unicode
1910 // conformance for a converter is that the <41> be processed and
1911 // correctly interpreted as <U+0041>. The converter could return
1912 // <U+FFFD, U+0041>, handling <F0 80 80> as a single error, or
1913 // <U+FFFD, U+FFFD, U+FFFD, U+0041>, handling each byte of
1914 // <F0 80 80> as a separate error, or could take other approaches
1915 // to signalling <F0 80 80> as an ill-formed code unit subsequence."
1916 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G48534
1917 1 static const char e1[] = "\xF0\x80\x80\x41";
1918 1 idx = 0;
1919 1 EXPECT_EQ(u_get_char(e1, 4, &idx), (CodePoint)-0xF0);
1920 1 ASSERT_EQ(idx, 1);
1921 1 EXPECT_EQ(u_get_char(e1, 4, &idx), (CodePoint)-0x80);
1922 1 ASSERT_EQ(idx, 2);
1923 1 EXPECT_EQ(u_get_char(e1, 4, &idx), (CodePoint)-0x80);
1924 1 ASSERT_EQ(idx, 3);
1925 1 EXPECT_EQ(u_get_char(e1, 4, &idx), 0x41);
1926 1 ASSERT_EQ(idx, 4);
1927 1 }
1928
1929 1 static void test_u_prev_char(TestContext *ctx)
1930 {
1931 1 const unsigned char *buf = "\xE6\xB7\xB1\xE5\x9C\xB3\xE5\xB8\x82"; // 深圳市
1932 1 size_t idx = 9;
1933 1 CodePoint c = u_prev_char(buf, &idx);
1934 1 EXPECT_EQ(c, 0x5E02);
1935 1 EXPECT_EQ(idx, 6);
1936 1 c = u_prev_char(buf, &idx);
1937 1 EXPECT_EQ(c, 0x5733);
1938 1 EXPECT_EQ(idx, 3);
1939 1 c = u_prev_char(buf, &idx);
1940 1 EXPECT_EQ(c, 0x6DF1);
1941 1 EXPECT_EQ(idx, 0);
1942
1943 1 idx = 1;
1944 1 c = u_prev_char(buf, &idx);
1945 1 EXPECT_EQ(c, -((CodePoint)0xE6UL));
1946 1 EXPECT_EQ(idx, 0);
1947
1948 1 buf = "Shenzhen";
1949 1 idx = 8;
1950 1 c = u_prev_char(buf, &idx);
1951 1 EXPECT_EQ(c, 'n');
1952 1 EXPECT_EQ(idx, 7);
1953 1 c = u_prev_char(buf, &idx);
1954 1 EXPECT_EQ(c, 'e');
1955 1 EXPECT_EQ(idx, 6);
1956
1957 1 buf = "\xF0\x9F\xA5\xA3\xF0\x9F\xA5\xA4"; // 🥣🥤
1958 1 idx = 8;
1959 1 c = u_prev_char(buf, &idx);
1960 1 EXPECT_EQ(c, 0x1F964);
1961 1 EXPECT_EQ(idx, 4);
1962 1 c = u_prev_char(buf, &idx);
1963 1 EXPECT_EQ(c, 0x1F963);
1964 1 EXPECT_EQ(idx, 0);
1965
1966 1 buf = "\xF0\xF5";
1967 1 idx = 2;
1968 1 c = u_prev_char(buf, &idx);
1969 1 EXPECT_EQ(c, -((CodePoint)buf[1]));
1970 1 EXPECT_EQ(idx, 1);
1971 1 c = u_prev_char(buf, &idx);
1972 1 EXPECT_EQ(c, -((CodePoint)buf[0]));
1973 1 EXPECT_EQ(idx, 0);
1974
1975 1 buf = "\xF5\xF0";
1976 1 idx = 2;
1977 1 c = u_prev_char(buf, &idx);
1978 1 EXPECT_EQ(c, -((CodePoint)buf[1]));
1979 1 EXPECT_EQ(idx, 1);
1980 1 c = u_prev_char(buf, &idx);
1981 1 EXPECT_EQ(c, -((CodePoint)buf[0]));
1982 1 EXPECT_EQ(idx, 0);
1983 1 }
1984
1985 1 static void test_ptr_array(TestContext *ctx)
1986 {
1987 1 PointerArray a = PTR_ARRAY_INIT;
1988 1 ptr_array_append(&a, NULL);
1989 1 ptr_array_append(&a, NULL);
1990 1 ptr_array_append(&a, xstrdup("foo"));
1991 1 ptr_array_append(&a, NULL);
1992 1 ptr_array_append(&a, xstrdup("bar"));
1993 1 ptr_array_append(&a, NULL);
1994 1 ptr_array_append(&a, NULL);
1995 1 EXPECT_EQ(a.count, 7);
1996
1997 1 ptr_array_trim_nulls(&a);
1998 1 EXPECT_EQ(a.count, 4);
1999 1 EXPECT_STREQ(a.ptrs[0], "foo");
2000 1 EXPECT_NULL(a.ptrs[1]);
2001 1 EXPECT_STREQ(a.ptrs[2], "bar");
2002 1 EXPECT_NULL(a.ptrs[3]);
2003 1 ptr_array_trim_nulls(&a);
2004 1 EXPECT_EQ(a.count, 4);
2005
2006 1 ptr_array_free(&a);
2007 1 EXPECT_EQ(a.count, 0);
2008 1 ptr_array_trim_nulls(&a);
2009 1 EXPECT_EQ(a.count, 0);
2010
2011 1 ptr_array_init(&a, 0);
2012 1 EXPECT_EQ(a.alloc, 0);
2013 1 EXPECT_NULL(a.ptrs);
2014 1 ptr_array_free(&a);
2015 1 ptr_array_init(&a, 1);
2016 1 EXPECT_EQ(a.alloc, 8);
2017 1 EXPECT_NONNULL(a.ptrs);
2018 1 ptr_array_free(&a);
2019
2020 // ptr_array_trim_nulls() should remove everything (i.e. not leave 1
2021 // trailing NULL) when all elements are NULL
2022 1 ptr_array_init(&a, 0);
2023 1 ptr_array_append(&a, NULL);
2024 1 ptr_array_append(&a, NULL);
2025 1 ptr_array_append(&a, NULL);
2026 1 EXPECT_EQ(a.count, 3);
2027 1 ptr_array_trim_nulls(&a);
2028 1 EXPECT_EQ(a.count, 0);
2029 1 ptr_array_free(&a);
2030 1 }
2031
2032 1 static void test_ptr_array_move(TestContext *ctx)
2033 {
2034 1 PointerArray a = PTR_ARRAY_INIT;
2035 1 ptr_array_append(&a, xstrdup("A"));
2036 1 ptr_array_append(&a, xstrdup("B"));
2037 1 ptr_array_append(&a, xstrdup("C"));
2038 1 ptr_array_append(&a, xstrdup("D"));
2039 1 ptr_array_append(&a, xstrdup("E"));
2040 1 ptr_array_append(&a, xstrdup("F"));
2041 1 EXPECT_EQ(a.count, 6);
2042
2043 1 ptr_array_move(&a, 0, 1);
2044 1 EXPECT_STREQ(a.ptrs[0], "B");
2045 1 EXPECT_STREQ(a.ptrs[1], "A");
2046
2047 1 ptr_array_move(&a, 1, 0);
2048 1 EXPECT_STREQ(a.ptrs[0], "A");
2049 1 EXPECT_STREQ(a.ptrs[1], "B");
2050
2051 1 ptr_array_move(&a, 1, 5);
2052 1 EXPECT_STREQ(a.ptrs[0], "A");
2053 1 EXPECT_STREQ(a.ptrs[1], "C");
2054 1 EXPECT_STREQ(a.ptrs[2], "D");
2055 1 EXPECT_STREQ(a.ptrs[3], "E");
2056 1 EXPECT_STREQ(a.ptrs[4], "F");
2057 1 EXPECT_STREQ(a.ptrs[5], "B");
2058
2059 1 ptr_array_move(&a, 5, 1);
2060 1 EXPECT_STREQ(a.ptrs[0], "A");
2061 1 EXPECT_STREQ(a.ptrs[1], "B");
2062 1 EXPECT_STREQ(a.ptrs[2], "C");
2063 1 EXPECT_STREQ(a.ptrs[3], "D");
2064 1 EXPECT_STREQ(a.ptrs[4], "E");
2065 1 EXPECT_STREQ(a.ptrs[5], "F");
2066
2067 1 ptr_array_move(&a, 0, 5);
2068 1 EXPECT_STREQ(a.ptrs[0], "B");
2069 1 EXPECT_STREQ(a.ptrs[1], "C");
2070 1 EXPECT_STREQ(a.ptrs[2], "D");
2071 1 EXPECT_STREQ(a.ptrs[3], "E");
2072 1 EXPECT_STREQ(a.ptrs[4], "F");
2073 1 EXPECT_STREQ(a.ptrs[5], "A");
2074
2075 1 ptr_array_move(&a, 5, 0);
2076 1 EXPECT_STREQ(a.ptrs[0], "A");
2077 1 EXPECT_STREQ(a.ptrs[1], "B");
2078 1 EXPECT_STREQ(a.ptrs[2], "C");
2079 1 EXPECT_STREQ(a.ptrs[3], "D");
2080 1 EXPECT_STREQ(a.ptrs[4], "E");
2081 1 EXPECT_STREQ(a.ptrs[5], "F");
2082
2083 1 ptr_array_move(&a, 5, 0);
2084 1 EXPECT_STREQ(a.ptrs[0], "F");
2085 1 EXPECT_STREQ(a.ptrs[1], "A");
2086 1 EXPECT_STREQ(a.ptrs[2], "B");
2087 1 EXPECT_STREQ(a.ptrs[3], "C");
2088 1 EXPECT_STREQ(a.ptrs[4], "D");
2089 1 EXPECT_STREQ(a.ptrs[5], "E");
2090
2091 1 ptr_array_move(&a, 4, 5);
2092 1 EXPECT_STREQ(a.ptrs[4], "E");
2093 1 EXPECT_STREQ(a.ptrs[5], "D");
2094
2095 1 ptr_array_move(&a, 1, 3);
2096 1 EXPECT_STREQ(a.ptrs[1], "B");
2097 1 EXPECT_STREQ(a.ptrs[2], "C");
2098 1 EXPECT_STREQ(a.ptrs[3], "A");
2099
2100 1 ptr_array_move(&a, 3, 3);
2101 1 EXPECT_STREQ(a.ptrs[3], "A");
2102 1 ptr_array_move(&a, 1, 1);
2103 1 EXPECT_STREQ(a.ptrs[1], "B");
2104 1 ptr_array_move(&a, 0, 0);
2105 1 EXPECT_STREQ(a.ptrs[0], "F");
2106
2107 1 ptr_array_free(&a);
2108 1 }
2109
2110 1 static void test_list(TestContext *ctx)
2111 {
2112 1 ListHead a, b, c;
2113 1 list_init(&b);
2114 1 EXPECT_TRUE(list_empty(&b));
2115
2116 1 list_insert_before(&a, &b);
2117 1 EXPECT_FALSE(list_empty(&a));
2118 1 EXPECT_FALSE(list_empty(&b));
2119 1 EXPECT_PTREQ(a.next, &b);
2120 1 EXPECT_PTREQ(a.prev, &b);
2121 1 EXPECT_PTREQ(b.next, &a);
2122 1 EXPECT_PTREQ(b.prev, &a);
2123
2124 1 list_insert_after(&c, &b);
2125 1 EXPECT_FALSE(list_empty(&a));
2126 1 EXPECT_FALSE(list_empty(&b));
2127 1 EXPECT_FALSE(list_empty(&c));
2128 1 EXPECT_PTREQ(a.next, &b);
2129 1 EXPECT_PTREQ(a.prev, &c);
2130 1 EXPECT_PTREQ(b.next, &c);
2131 1 EXPECT_PTREQ(b.prev, &a);
2132 1 EXPECT_PTREQ(c.next, &a);
2133 1 EXPECT_PTREQ(c.prev, &b);
2134
2135 1 list_remove(&b);
2136 1 EXPECT_FALSE(list_empty(&a));
2137 1 EXPECT_FALSE(list_empty(&c));
2138 1 EXPECT_PTREQ(a.next, &c);
2139 1 EXPECT_PTREQ(a.prev, &c);
2140 1 EXPECT_PTREQ(c.next, &a);
2141 1 EXPECT_PTREQ(c.prev, &a);
2142 1 EXPECT_NULL(b.next);
2143 1 EXPECT_NULL(b.prev);
2144 1 }
2145
2146 1 static void test_hashmap(TestContext *ctx)
2147 {
2148 1 static const char strings[][8] = {
2149 "foo", "bar", "quux", "etc", "",
2150 "A", "B", "C", "D", "E", "F", "G",
2151 "a", "b", "c", "d", "e", "f", "g",
2152 "test", "1234567", "..", "...",
2153 "\x01\x02\x03 \t\xfe\xff",
2154 };
2155
2156 1 HashMap map;
2157 1 hashmap_init(&map, ARRAYLEN(strings));
2158 1 ASSERT_NONNULL(map.entries);
2159 1 EXPECT_EQ(map.mask, 31);
2160 1 EXPECT_EQ(map.count, 0);
2161 1 EXPECT_NULL(hashmap_find(&map, "foo"));
2162
2163 1 static const char value[] = "VALUE";
2164
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 FOR_EACH_I(i, strings) {
2165 24 const char *key = strings[i];
2166 24 ASSERT_EQ(key[sizeof(strings[0]) - 1], '\0');
2167 24 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2168 24 HashMapEntry *e = hashmap_find(&map, key);
2169 24 ASSERT_NONNULL(e);
2170 24 EXPECT_STREQ(e->key, key);
2171 24 EXPECT_PTREQ(e->value, value);
2172 }
2173
2174 1 EXPECT_EQ(map.count, 24);
2175 1 EXPECT_EQ(map.mask, 31);
2176
2177 1 HashMapIter it = hashmap_iter(&map);
2178 1 EXPECT_PTREQ(it.map, &map);
2179 1 EXPECT_NULL(it.entry);
2180 1 EXPECT_EQ(it.idx, 0);
2181
2182
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 while (hashmap_next(&it)) {
2183 24 ASSERT_NONNULL(it.entry);
2184 24 ASSERT_NONNULL(it.entry->key);
2185 24 EXPECT_PTREQ(it.entry->value, value);
2186 }
2187
2188
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 FOR_EACH_I(i, strings) {
2189 24 const char *key = strings[i];
2190 24 HashMapEntry *e = hashmap_find(&map, key);
2191 24 ASSERT_NONNULL(e);
2192 24 EXPECT_STREQ(e->key, key);
2193 24 EXPECT_PTREQ(e->value, value);
2194 24 EXPECT_PTREQ(hashmap_remove(&map, key), value);
2195 24 EXPECT_STREQ(e->key, NULL);
2196 24 EXPECT_UINT_EQ(e->hash, 0xdead);
2197 24 EXPECT_NULL(hashmap_find(&map, key));
2198 }
2199
2200 1 EXPECT_EQ(map.count, 0);
2201 1 it = hashmap_iter(&map);
2202 1 EXPECT_FALSE(hashmap_next(&it));
2203
2204 1 EXPECT_PTREQ(hashmap_insert(&map, xstrdup("new"), (void*)value), value);
2205 1 ASSERT_NONNULL(hashmap_find(&map, "new"));
2206 1 EXPECT_STREQ(hashmap_find(&map, "new")->key, "new");
2207 1 EXPECT_EQ(map.count, 1);
2208
2209
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 FOR_EACH_I(i, strings) {
2210 24 const char *key = strings[i];
2211 24 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2212 24 HashMapEntry *e = hashmap_find(&map, key);
2213 24 ASSERT_NONNULL(e);
2214 24 EXPECT_STREQ(e->key, key);
2215 24 EXPECT_PTREQ(e->value, value);
2216 }
2217
2218 1 EXPECT_EQ(map.count, 25);
2219
2220
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 FOR_EACH_I(i, strings) {
2221 24 const char *key = strings[i];
2222 24 HashMapEntry *e = hashmap_find(&map, key);
2223 24 ASSERT_NONNULL(e);
2224 24 EXPECT_STREQ(e->key, key);
2225 24 EXPECT_PTREQ(hashmap_remove(&map, key), value);
2226 24 EXPECT_STREQ(e->key, NULL);
2227 24 EXPECT_UINT_EQ(e->hash, 0xdead);
2228 24 EXPECT_NULL(hashmap_find(&map, key));
2229 }
2230
2231 1 EXPECT_EQ(map.count, 1);
2232 1 EXPECT_NULL(hashmap_remove(&map, "non-existent-key"));
2233 1 EXPECT_EQ(map.count, 1);
2234 1 EXPECT_PTREQ(hashmap_remove(&map, "new"), value);
2235 1 EXPECT_EQ(map.count, 0);
2236
2237 1 it = hashmap_iter(&map);
2238 1 EXPECT_FALSE(hashmap_next(&it));
2239
2240 1 hashmap_free(&map, NULL);
2241 1 EXPECT_NULL(map.entries);
2242 1 EXPECT_EQ(map.count, 0);
2243 1 EXPECT_EQ(map.mask, 0);
2244
2245 1 hashmap_init(&map, 0);
2246 1 ASSERT_NONNULL(map.entries);
2247 1 EXPECT_EQ(map.mask, 7);
2248 1 EXPECT_EQ(map.count, 0);
2249 1 hashmap_free(&map, NULL);
2250 1 EXPECT_NULL(map.entries);
2251
2252 1 hashmap_init(&map, 13);
2253 1 ASSERT_NONNULL(map.entries);
2254 1 EXPECT_EQ(map.mask, 31);
2255 1 EXPECT_EQ(map.count, 0);
2256
2257
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 1 times.
381 for (unsigned int i = 1; i <= 380; i++) {
2258 380 char key[4];
2259 380 ASSERT_TRUE(buf_uint_to_str(i, key) < sizeof(key));
2260 380 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2261 380 HashMapEntry *e = hashmap_find(&map, key);
2262 380 ASSERT_NONNULL(e);
2263 380 EXPECT_STREQ(e->key, key);
2264 380 EXPECT_PTREQ(e->value, value);
2265 }
2266
2267 1 EXPECT_EQ(map.count, 380);
2268 1 EXPECT_EQ(map.mask, 511);
2269 1 hashmap_free(&map, NULL);
2270
2271 1 const char val[] = "VAL";
2272 1 char *key = xstrdup("KEY");
2273 1 EXPECT_NULL(hashmap_insert_or_replace(&map, key, (char*)val));
2274 1 EXPECT_EQ(map.count, 1);
2275 1 EXPECT_STREQ(hashmap_get(&map, "KEY"), val);
2276
2277 1 const char new_val[] = "NEW";
2278 1 char *duplicate_key = xstrdup(key);
2279 1 EXPECT_PTREQ(val, hashmap_insert_or_replace(&map, duplicate_key, (char*)new_val));
2280 1 EXPECT_EQ(map.count, 1);
2281 1 EXPECT_STREQ(hashmap_get(&map, "KEY"), new_val);
2282 1 hashmap_free(&map, NULL);
2283 1 }
2284
2285 1 static void test_hashset(TestContext *ctx)
2286 {
2287 1 static const char *const strings[] = {
2288 "foo", "Foo", "bar", "quux", "etc",
2289 "\t\xff\x80\b", "\t\t\t", "\x01\x02\x03\xfe\xff",
2290 #if __STDC_VERSION__ >= 201112L
2291 u8"ภาษาไทย",
2292 u8"中文",
2293 u8"日本語",
2294 #endif
2295 };
2296
2297 1 HashSet set;
2298 1 hashset_init(&set, ARRAYLEN(strings), false);
2299 1 EXPECT_EQ(set.nr_entries, 0);
2300 1 EXPECT_NULL(hashset_get(&set, "foo", 3));
2301
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 FOR_EACH_I(i, strings) {
2302 11 hashset_insert(&set, strings[i], strlen(strings[i]));
2303 }
2304
2305 1 EXPECT_EQ(set.nr_entries, ARRAYLEN(strings));
2306 1 EXPECT_NONNULL(hashset_get(&set, "\t\xff\x80\b", 4));
2307 1 EXPECT_NONNULL(hashset_get(&set, "foo", 3));
2308 1 EXPECT_NONNULL(hashset_get(&set, "Foo", 3));
2309
2310 1 EXPECT_NULL(hashset_get(&set, "FOO", 3));
2311 1 EXPECT_NULL(hashset_get(&set, "", 0));
2312 1 EXPECT_NULL(hashset_get(&set, NULL, 0));
2313 1 EXPECT_NULL(hashset_get(&set, "\0", 1));
2314
2315 1 const char *last_string = strings[ARRAYLEN(strings) - 1];
2316 1 EXPECT_NONNULL(hashset_get(&set, last_string, strlen(last_string)));
2317
2318
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 FOR_EACH_I(i, strings) {
2319 11 const char *str = strings[i];
2320 11 const size_t len = strlen(str);
2321 11 EXPECT_NONNULL(hashset_get(&set, str, len));
2322 11 EXPECT_NULL(hashset_get(&set, str, len - 1));
2323 11 EXPECT_NULL(hashset_get(&set, str + 1, len - 1));
2324 }
2325
2326 1 hashset_free(&set);
2327 1 hashset_init(&set, 0, true);
2328 1 EXPECT_EQ(set.nr_entries, 0);
2329 1 hashset_insert(&set, STRN("foo"));
2330 1 hashset_insert(&set, STRN("Foo"));
2331 1 EXPECT_EQ(set.nr_entries, 1);
2332 1 EXPECT_NONNULL(hashset_get(&set, STRN("foo")));
2333 1 EXPECT_NONNULL(hashset_get(&set, STRN("FOO")));
2334 1 EXPECT_NONNULL(hashset_get(&set, STRN("fOO")));
2335 1 hashset_free(&set);
2336
2337 // Check that hashset_insert() returns existing entries instead of
2338 // inserting duplicates
2339 1 hashset_init(&set, 0, false);
2340 1 EXPECT_EQ(set.nr_entries, 0);
2341 1 HashSetEntry *e1 = hashset_insert(&set, STRN("foo"));
2342 1 EXPECT_EQ(e1->str_len, 3);
2343 1 EXPECT_STREQ(e1->str, "foo");
2344 1 EXPECT_EQ(set.nr_entries, 1);
2345 1 HashSetEntry *e2 = hashset_insert(&set, STRN("foo"));
2346 1 EXPECT_PTREQ(e1, e2);
2347 1 EXPECT_EQ(set.nr_entries, 1);
2348 1 hashset_free(&set);
2349
2350 1 hashset_init(&set, 0, false);
2351 // Initial table size should be 16 (minimum + load factor + rounding)
2352 1 EXPECT_EQ(set.table_size, 16);
2353
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 1 times.
81 for (unsigned int i = 1; i <= 80; i++) {
2354 80 char buf[4];
2355 80 size_t len = buf_uint_to_str(i, buf);
2356 80 ASSERT_TRUE(len < sizeof(buf));
2357 80 hashset_insert(&set, buf, len);
2358 }
2359 1 EXPECT_EQ(set.nr_entries, 80);
2360 1 EXPECT_NONNULL(hashset_get(&set, STRN("1")));
2361 1 EXPECT_NONNULL(hashset_get(&set, STRN("80")));
2362 1 EXPECT_NULL(hashset_get(&set, STRN("0")));
2363 1 EXPECT_NULL(hashset_get(&set, STRN("81")));
2364 // Table size should be the first power of 2 larger than the number
2365 // of entries (including load factor adjustment)
2366 1 EXPECT_EQ(set.table_size, 128);
2367 1 hashset_free(&set);
2368 1 }
2369
2370 1 static void test_intmap(TestContext *ctx)
2371 {
2372 1 IntMap map = INTMAP_INIT;
2373 1 EXPECT_NULL(intmap_find(&map, 0));
2374 1 EXPECT_NULL(intmap_get(&map, 0));
2375 1 intmap_free(&map, free);
2376
2377 1 const char value[] = "value";
2378 1 EXPECT_NULL(intmap_insert_or_replace(&map, 0, xstrdup(value)));
2379 1 EXPECT_NULL(intmap_insert_or_replace(&map, 1, xstrdup(value)));
2380 1 EXPECT_NULL(intmap_insert_or_replace(&map, 2, xstrdup(value)));
2381 1 EXPECT_NULL(intmap_insert_or_replace(&map, 4, xstrdup(value)));
2382 1 EXPECT_EQ(map.count, 4);
2383 1 EXPECT_EQ(map.mask, 7);
2384
2385 1 char *replaced = intmap_insert_or_replace(&map, 0, xstrdup(value));
2386 1 EXPECT_STREQ(replaced, value);
2387 1 free(replaced);
2388 1 EXPECT_EQ(map.tombstones, 0);
2389 1 EXPECT_STREQ(intmap_get(&map, 0), value);
2390
2391 1 char *removed = intmap_remove(&map, 0);
2392 1 EXPECT_STREQ(removed, value);
2393 1 free(removed);
2394 1 EXPECT_EQ(map.tombstones, 1);
2395 1 EXPECT_NULL(intmap_get(&map, 0));
2396
2397 1 EXPECT_NULL(intmap_insert_or_replace(&map, 100, xstrdup(value)));
2398 1 EXPECT_NULL(intmap_insert_or_replace(&map, 488, xstrdup(value)));
2399 1 EXPECT_NULL(intmap_insert_or_replace(&map, 899, xstrdup(value)));
2400 1 EXPECT_NULL(intmap_insert_or_replace(&map, 256, xstrdup(value)));
2401 1 EXPECT_EQ(map.count, 7);
2402 1 EXPECT_EQ(map.mask, 15);
2403
2404 1 intmap_free(&map, free);
2405 1 }
2406
2407 1 static void test_round_size_to_next_multiple(TestContext *ctx)
2408 {
2409 1 EXPECT_EQ(round_size_to_next_multiple(3, 8), 8);
2410 1 EXPECT_EQ(round_size_to_next_multiple(8, 8), 8);
2411 1 EXPECT_EQ(round_size_to_next_multiple(9, 8), 16);
2412 1 EXPECT_EQ(round_size_to_next_multiple(0, 8), 0);
2413 1 EXPECT_EQ(round_size_to_next_multiple(0, 16), 0);
2414 1 EXPECT_EQ(round_size_to_next_multiple(1, 16), 16);
2415 1 EXPECT_EQ(round_size_to_next_multiple(123, 16), 128);
2416 1 EXPECT_EQ(round_size_to_next_multiple(4, 64), 64);
2417 1 EXPECT_EQ(round_size_to_next_multiple(80, 64), 128);
2418 1 EXPECT_EQ(round_size_to_next_multiple(256, 256), 256);
2419 1 EXPECT_EQ(round_size_to_next_multiple(257, 256), 512);
2420 1 EXPECT_EQ(round_size_to_next_multiple(8000, 256), 8192);
2421 1 }
2422
2423 1 static void test_round_size_to_next_power_of_2(TestContext *ctx)
2424 {
2425 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(0), 1);
2426 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(1), 1);
2427 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(2), 2);
2428 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(3), 4);
2429 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(4), 4);
2430 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(5), 8);
2431 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(8), 8);
2432 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(9), 16);
2433 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(17), 32);
2434 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(61), 64);
2435 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(64), 64);
2436 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(65), 128);
2437 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(200), 256);
2438 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(1000), 1024);
2439 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(5500), 8192);
2440
2441 1 const size_t size_max = (size_t)-1;
2442 1 const size_t pow2_max = ~(size_max >> 1);
2443 1 EXPECT_TRUE(IS_POWER_OF_2(pow2_max));
2444 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(size_max >> 1), pow2_max);
2445 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(pow2_max), pow2_max);
2446 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(pow2_max - 1), pow2_max);
2447
2448 // Note: returns 0 on overflow
2449 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(pow2_max + 1), 0);
2450 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(size_max), 0);
2451 1 EXPECT_UINT_EQ(round_size_to_next_power_of_2(size_max - 1), 0);
2452 1 }
2453
2454 1 static void test_popcount(TestContext *ctx)
2455 {
2456 1 EXPECT_EQ(u32_popcount(0), 0);
2457 1 EXPECT_EQ(u32_popcount(1), 1);
2458 1 EXPECT_EQ(u32_popcount(11), 3);
2459 1 EXPECT_EQ(u32_popcount(128), 1);
2460 1 EXPECT_EQ(u32_popcount(255), 8);
2461 1 EXPECT_EQ(u32_popcount(UINT32_MAX), 32);
2462 1 EXPECT_EQ(u32_popcount(UINT32_MAX - 1), 31);
2463 1 EXPECT_EQ(u32_popcount(U32(0xE10F02C9)), 13);
2464
2465 1 EXPECT_EQ(u64_popcount(0), 0);
2466 1 EXPECT_EQ(u64_popcount(1), 1);
2467 1 EXPECT_EQ(u64_popcount(255), 8);
2468 1 EXPECT_EQ(u64_popcount(UINT64_MAX), 64);
2469 1 EXPECT_EQ(u64_popcount(UINT64_MAX - 1), 63);
2470 1 EXPECT_EQ(u64_popcount(U64(0xFFFFFFFFFF)), 40);
2471 1 EXPECT_EQ(u64_popcount(U64(0x10000000000)), 1);
2472 1 EXPECT_EQ(u64_popcount(U64(0x9010F0EEC2003B70)), 24);
2473
2474
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 for (unsigned int i = 0; i < 32; i++) {
2475 32 IEXPECT_EQ(u32_popcount(UINT32_MAX << i), 32 - i);
2476 32 IEXPECT_EQ(u32_popcount(UINT32_MAX >> i), 32 - i);
2477 32 IEXPECT_EQ(u32_popcount(U32(1) << i), 1);
2478 }
2479
2480
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (unsigned int i = 0; i < 64; i++) {
2481 64 IEXPECT_EQ(u64_popcount(UINT64_MAX << i), 64 - i);
2482 64 IEXPECT_EQ(u64_popcount(UINT64_MAX >> i), 64 - i);
2483 64 IEXPECT_EQ(u64_popcount(U64(1) << i), 1);
2484 }
2485 1 }
2486
2487 1 static void test_ctz(TestContext *ctx)
2488 {
2489 1 EXPECT_EQ(u32_ctz(1), 0);
2490 1 EXPECT_EQ(u32_ctz(11), 0);
2491 1 EXPECT_EQ(u32_ctz(127), 0);
2492 1 EXPECT_EQ(u32_ctz(128), 7);
2493 1 EXPECT_EQ(u32_ctz(129), 0);
2494 1 EXPECT_EQ(u32_ctz(130), 1);
2495 1 EXPECT_EQ(u32_ctz(255), 0);
2496 1 EXPECT_EQ(u32_ctz(UINT32_MAX), 0);
2497 1 EXPECT_EQ(u32_ctz(UINT32_MAX - 1), 1);
2498 1 EXPECT_EQ(u32_ctz(U32(0xE10F02C9)), 0);
2499 1 EXPECT_EQ(u32_ctz(U32(0xE10F02CC)), 2);
2500 1 }
2501
2502 1 static void test_ffs(TestContext *ctx)
2503 {
2504 1 EXPECT_EQ(u32_ffs(0), 0);
2505 1 EXPECT_EQ(u32_ffs(1), 1);
2506 1 EXPECT_EQ(u32_ffs(6), 2);
2507 1 EXPECT_EQ(u32_ffs(8), 4);
2508 1 EXPECT_EQ(u32_ffs(255), 1);
2509 1 EXPECT_EQ(u32_ffs(256), 9);
2510 1 EXPECT_EQ(u32_ffs(~U32(255)), 9);
2511 1 EXPECT_EQ(u32_ffs(UINT32_MAX), 1);
2512 1 EXPECT_EQ(u32_ffs(UINT32_MAX - 1), 2);
2513 1 EXPECT_EQ(u32_ffs(U32(1) << 31), 32);
2514 1 EXPECT_EQ(u32_ffs(U32(1) << 30), 31);
2515 1 EXPECT_EQ(u32_ffs(U32(1) << 18), 19);
2516 1 }
2517
2518 1 static void test_lsbit(TestContext *ctx)
2519 {
2520 1 EXPECT_EQ(u32_lsbit(0), 0);
2521 1 EXPECT_EQ(u32_lsbit(1), 1);
2522 1 EXPECT_EQ(u32_lsbit(2), 2);
2523 1 EXPECT_EQ(u32_lsbit(3), 1);
2524 1 EXPECT_EQ(u32_lsbit(4), 4);
2525 1 EXPECT_EQ(u32_lsbit(255), 1);
2526 1 EXPECT_EQ(u32_lsbit(256), 256);
2527 1 EXPECT_EQ(u32_lsbit(257), 1);
2528 1 EXPECT_EQ(u32_lsbit(258), 2);
2529 1 EXPECT_EQ(u32_lsbit(1u << 31), 1u << 31);
2530 1 EXPECT_EQ(u32_lsbit(1u << 30), 1u << 30);
2531 1 EXPECT_EQ(u32_lsbit(7u << 30), 1u << 30);
2532 1 EXPECT_EQ(u32_lsbit(UINT32_MAX), 1);
2533 1 EXPECT_EQ(u32_lsbit(UINT32_MAX << 25), 1u << 25);
2534
2535
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 1 times.
70 for (uint32_t x = 1; x < 70; x++) {
2536 69 uint32_t lsb = u32_lsbit(x);
2537 69 EXPECT_TRUE(IS_POWER_OF_2(lsb));
2538 69 EXPECT_TRUE(lsb & x);
2539 }
2540 1 }
2541
2542 1 static void test_path_dirname_and_path_basename(TestContext *ctx)
2543 {
2544 1 static const struct {
2545 const char *path;
2546 const char *dirname;
2547 const char *basename;
2548 } tests[] = {
2549 {"/home/user/example.txt", "/home/user", "example.txt"},
2550 {"./../dir/example.txt", "./../dir", "example.txt"},
2551 {"/usr/bin/", "/usr/bin", ""},
2552 {"example.txt", ".", "example.txt"},
2553 {"/usr/lib", "/usr", "lib"},
2554 {"/usr", "/", "usr"},
2555 {"usr", ".", "usr"},
2556 {"/", "/", ""},
2557 {".", ".", "."},
2558 {"..", ".", ".."},
2559 {"", ".", ""},
2560 };
2561
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 FOR_EACH_I(i, tests) {
2562 11 char *dir = path_dirname(tests[i].path);
2563 11 IEXPECT_STREQ(dir, tests[i].dirname);
2564 11 free(dir);
2565 11 IEXPECT_STREQ(path_basename(tests[i].path), tests[i].basename);
2566 }
2567 1 }
2568
2569 1 static void test_path_relative(TestContext *ctx)
2570 {
2571 1 static const struct {
2572 const char *cwd;
2573 const char *path;
2574 const char *result;
2575 } tests[] = { // NOTE: at most 2 ".." components allowed in relative name
2576 { "/", "/", "/" },
2577 { "/", "/file", "file" },
2578 { "/a/b/c/d", "/a/b/file", "../../file" },
2579 { "/a/b/c/d/e", "/a/b/file", "/a/b/file" },
2580 { "/a/foobar", "/a/foo/file", "../foo/file" },
2581 { "/home/user", "/home/userx", "../userx"},
2582 { "/home/user", "/home/use", "../use"},
2583 { "/home/user", "/home/user", "."},
2584 { "/home", "/home/user", "user"},
2585 };
2586
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 FOR_EACH_I(i, tests) {
2587 9 char *result = path_relative(tests[i].path, tests[i].cwd);
2588 9 IEXPECT_STREQ(tests[i].result, result);
2589 9 free(result);
2590 }
2591 1 }
2592
2593 1 static void test_path_slice_relative(TestContext *ctx)
2594 {
2595 1 const char *abs = "/a/b/c/d";
2596 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c/d/e"), abs);
2597 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/file"), abs);
2598 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c/d"), ".");
2599 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c"), "d");
2600 1 EXPECT_STREQ(path_slice_relative(abs, "/"), "a/b/c/d");
2601 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c"), abs + STRLEN("/a/b/c/"));
2602 1 EXPECT_STREQ(path_slice_relative("/", "/"), "/");
2603 1 EXPECT_STREQ(path_slice_relative("/aa/bb/ccX", "/aa/bb/cc"), "/aa/bb/ccX");
2604 1 }
2605
2606 1 static void test_short_filename_cwd(TestContext *ctx)
2607 {
2608 1 const StringView home = STRING_VIEW("/home/user");
2609 1 char *s = short_filename_cwd("/home/user", "/home/user", &home);
2610 1 EXPECT_STREQ(s, ".");
2611 1 free(s);
2612
2613 1 s = short_filename_cwd("/home/use", "/home/user", &home);
2614 1 EXPECT_STREQ(s, "../use");
2615 1 free(s);
2616
2617 1 s = short_filename_cwd("/a/b/c/d", "/a/x/y/file", &home);
2618 1 EXPECT_STREQ(s, "/a/b/c/d");
2619 1 free(s);
2620
2621 1 s = short_filename_cwd("/home/user/file", "/home/user/cwd", &home);
2622 1 EXPECT_STREQ(s, "~/file");
2623 1 free(s);
2624
2625 1 const char abs[] = "/a/b";
2626 1 const char cwd[] = "/a/x/c";
2627 1 char *rel = path_relative(abs, cwd);
2628 1 EXPECT_TRUE(strlen(abs) < strlen(rel));
2629 1 EXPECT_STREQ(rel, "../../b");
2630 1 free(rel);
2631 1 s = short_filename_cwd(abs, cwd, &home);
2632 1 EXPECT_STREQ(s, "/a/b");
2633 1 free(s);
2634 1 }
2635
2636 1 static void test_short_filename(TestContext *ctx)
2637 {
2638 1 const StringView home = STRING_VIEW("/home/user");
2639 1 const char rel[] = "test/main.c";
2640 1 char *abs = path_absolute(rel);
2641 1 ASSERT_NONNULL(abs);
2642 1 char *s = short_filename(abs, &home);
2643 1 EXPECT_STREQ(s, rel);
2644 1 free(abs);
2645 1 free(s);
2646
2647 1 s = short_filename("/home/user/subdir/file.txt", &home);
2648 1 EXPECT_STREQ(s, "~/subdir/file.txt");
2649 1 free(s);
2650
2651 1 s = short_filename("/x/y/z", &home);
2652 1 EXPECT_STREQ(s, "/x/y/z");
2653 1 free(s);
2654 1 }
2655
2656 1 static void test_path_absolute(TestContext *ctx)
2657 {
2658 1 char *path = path_absolute("///dev///");
2659 1 EXPECT_STREQ(path, "/dev");
2660 1 free(path);
2661
2662 1 path = path_absolute("///dev///..///dev//");
2663 1 EXPECT_STREQ(path, "/dev");
2664 1 free(path);
2665
2666 1 path = path_absolute("///dev//n0nexist3nt-file");
2667 1 EXPECT_STREQ(path, "/dev/n0nexist3nt-file");
2668 1 free(path);
2669
2670 1 errno = 0;
2671 1 path = path_absolute("/dev/-n0n-existent-dir-[];/file");
2672 1 EXPECT_EQ(errno, ENOENT);
2673 1 EXPECT_STREQ(path, NULL);
2674 1 free(path);
2675
2676 1 path = path_absolute("///../..//./");
2677 1 EXPECT_STREQ(path, "/");
2678 1 free(path);
2679
2680 1 path = path_absolute("/");
2681 1 EXPECT_STREQ(path, "/");
2682 1 free(path);
2683
2684 1 path = path_absolute("");
2685 1 EXPECT_STREQ(path, NULL);
2686 1 free(path);
2687
2688 1 static const char linkpath[] = "./build/test/../test/test-symlink";
2689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (symlink("../gen/platform.mk", linkpath) != 0) {
2690 TEST_FAIL("symlink() failed: %s", strerror(errno));
2691 return;
2692 }
2693 1 test_pass(ctx);
2694
2695 1 path = path_absolute(linkpath);
2696 1 EXPECT_EQ(unlink(linkpath), 0);
2697 1 ASSERT_NONNULL(path);
2698 1 EXPECT_STREQ(path_basename(path), "platform.mk");
2699 1 free(path);
2700 }
2701
2702 1 static void test_path_join(TestContext *ctx)
2703 {
2704 1 char *p = path_join("/", "file");
2705 1 EXPECT_STREQ(p, "/file");
2706 1 free(p);
2707 1 p = path_join("foo", "bar");
2708 1 EXPECT_STREQ(p, "foo/bar");
2709 1 free(p);
2710 1 p = path_join("foo/", "bar");
2711 1 EXPECT_STREQ(p, "foo/bar");
2712 1 free(p);
2713 1 p = path_join("", "bar");
2714 1 EXPECT_STREQ(p, "bar");
2715 1 free(p);
2716 1 p = path_join("foo", "");
2717 1 EXPECT_STREQ(p, "foo");
2718 1 free(p);
2719 1 p = path_join("", "");
2720 1 EXPECT_STREQ(p, "");
2721 1 free(p);
2722 1 p = path_join("/", "");
2723 1 EXPECT_STREQ(p, "/");
2724 1 free(p);
2725 1 p = path_join("/home/user", ".dte");
2726 1 EXPECT_STREQ(p, "/home/user/.dte");
2727 1 free(p);
2728 1 p = path_join("/home/user/", ".dte");
2729 1 EXPECT_STREQ(p, "/home/user/.dte");
2730 1 free(p);
2731 1 p = path_join("/home/user//", ".dte");
2732 1 EXPECT_STREQ(p, "/home/user//.dte");
2733 1 free(p);
2734
2735 1 p = path_joinx("foo", "bar", true);
2736 1 EXPECT_STREQ(p, "foo/bar/");
2737 1 free(p);
2738 1 p = path_joinx("foo", "bar", false);
2739 1 EXPECT_STREQ(p, "foo/bar");
2740 1 free(p);
2741 1 p = path_joinx("", "", true);
2742 1 EXPECT_STREQ(p, "");
2743 1 free(p);
2744 1 p = path_joinx("/", "", true);
2745 1 EXPECT_STREQ(p, "/");
2746 1 free(p);
2747 1 p = path_joinx("", "file", true);
2748 1 EXPECT_STREQ(p, "file/");
2749 1 free(p);
2750 1 p = path_joinx("", "file", false);
2751 1 EXPECT_STREQ(p, "file");
2752 1 free(p);
2753 1 p = path_joinx("", "file/", true);
2754 1 EXPECT_STREQ(p, "file/");
2755 1 free(p);
2756 1 }
2757
2758 1 static void test_path_parent(TestContext *ctx)
2759 {
2760 1 StringView sv = STRING_VIEW("/a/foo/bar/etc/file");
2761 1 EXPECT_EQ(sv.length, 19);
2762 1 EXPECT_TRUE(path_parent(&sv));
2763 1 EXPECT_EQ(sv.length, 14);
2764 1 EXPECT_TRUE(path_parent(&sv));
2765 1 EXPECT_EQ(sv.length, 10);
2766 1 EXPECT_TRUE(path_parent(&sv));
2767 1 EXPECT_EQ(sv.length, 6);
2768 1 EXPECT_TRUE(path_parent(&sv));
2769 1 EXPECT_EQ(sv.length, 2);
2770 1 EXPECT_TRUE(path_parent(&sv));
2771 1 EXPECT_EQ(sv.length, 1);
2772 1 EXPECT_FALSE(path_parent(&sv));
2773 1 EXPECT_EQ(sv.length, 1);
2774
2775 1 StringView sv2 = STRING_VIEW("/etc/foo/x/y/");
2776 1 EXPECT_EQ(sv2.length, 13);
2777 1 EXPECT_TRUE(path_parent(&sv2));
2778 1 EXPECT_EQ(sv2.length, 10);
2779 1 EXPECT_TRUE(path_parent(&sv2));
2780 1 EXPECT_EQ(sv2.length, 8);
2781 1 EXPECT_TRUE(path_parent(&sv2));
2782 1 EXPECT_EQ(sv2.length, 4);
2783 1 EXPECT_TRUE(path_parent(&sv2));
2784 1 EXPECT_EQ(sv2.length, 1);
2785 1 EXPECT_FALSE(path_parent(&sv2));
2786 1 EXPECT_EQ(sv2.length, 1);
2787 1 }
2788
2789 1 static void test_size_increment_wrapped(TestContext *ctx)
2790 {
2791 1 EXPECT_EQ(size_increment_wrapped(0, 1), 0);
2792 1 EXPECT_EQ(size_increment_wrapped(3, 5), 4);
2793 1 EXPECT_EQ(size_increment_wrapped(4, 5), 0);
2794 1 EXPECT_EQ(size_increment_wrapped(0, 5), 1);
2795
2796
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (size_t m = 1; m < 9; m++) {
2797
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
44 for (size_t x = 0; x < m; x++) {
2798 36 EXPECT_EQ(size_increment_wrapped(x, m), (x + 1) % m);
2799 }
2800 }
2801 1 }
2802
2803 1 static void test_size_decrement_wrapped(TestContext *ctx)
2804 {
2805 1 EXPECT_EQ(size_decrement_wrapped(0, 1), 0);
2806 1 EXPECT_EQ(size_decrement_wrapped(1, 450), 0);
2807 1 EXPECT_EQ(size_decrement_wrapped(0, 450), 449);
2808 1 EXPECT_EQ(size_decrement_wrapped(449, 450), 448);
2809
2810
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (size_t m = 1; m < 9; m++) {
2811 8 EXPECT_EQ(size_decrement_wrapped(0, m), m - 1);
2812
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
36 for (size_t x = 1; x < m; x++) {
2813 28 EXPECT_EQ(size_decrement_wrapped(x, m), (x - 1) % m);
2814 }
2815 }
2816 1 }
2817
2818 1 static void test_size_multiply_overflows(TestContext *ctx)
2819 {
2820 1 size_t r = 0;
2821 1 EXPECT_FALSE(size_multiply_overflows(10, 20, &r));
2822 1 EXPECT_UINT_EQ(r, 200);
2823 1 EXPECT_FALSE(size_multiply_overflows(0, 0, &r));
2824 1 EXPECT_UINT_EQ(r, 0);
2825 1 EXPECT_FALSE(size_multiply_overflows(1, 0, &r));
2826 1 EXPECT_UINT_EQ(r, 0);
2827 1 EXPECT_FALSE(size_multiply_overflows(0, 1, &r));
2828 1 EXPECT_UINT_EQ(r, 0);
2829 1 EXPECT_FALSE(size_multiply_overflows(0, SIZE_MAX, &r));
2830 1 EXPECT_UINT_EQ(r, 0);
2831 1 EXPECT_FALSE(size_multiply_overflows(SIZE_MAX, 0, &r));
2832 1 EXPECT_UINT_EQ(r, 0);
2833 1 EXPECT_FALSE(size_multiply_overflows(1, SIZE_MAX, &r));
2834 1 EXPECT_UINT_EQ(r, SIZE_MAX);
2835 1 EXPECT_FALSE(size_multiply_overflows(2, SIZE_MAX / 3, &r));
2836 1 EXPECT_UINT_EQ(r, 2 * (SIZE_MAX / 3));
2837 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, 2, &r));
2838 1 EXPECT_TRUE(size_multiply_overflows(2, SIZE_MAX, &r));
2839 1 EXPECT_TRUE(size_multiply_overflows(3, SIZE_MAX / 2, &r));
2840 1 EXPECT_TRUE(size_multiply_overflows(32767, SIZE_MAX, &r));
2841 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX, &r));
2842 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
2843 1 }
2844
2845 1 static void test_size_add_overflows(TestContext *ctx)
2846 {
2847 1 size_t r = 0;
2848 1 EXPECT_FALSE(size_add_overflows(10, 20, &r));
2849 1 EXPECT_UINT_EQ(r, 30);
2850 1 EXPECT_FALSE(size_add_overflows(SIZE_MAX, 0, &r));
2851 1 EXPECT_UINT_EQ(r, SIZE_MAX);
2852 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 1, &r));
2853 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 16, &r));
2854 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX, &r));
2855 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
2856 1 }
2857
2858 1 static void test_xmul(TestContext *ctx)
2859 {
2860 1 const size_t halfmax = SIZE_MAX / 2;
2861 1 EXPECT_UINT_EQ(xmul(2, halfmax), 2 * halfmax);
2862 1 EXPECT_UINT_EQ(xmul(8, 8), 64);
2863 1 EXPECT_UINT_EQ(xmul(1, SIZE_MAX), SIZE_MAX);
2864 1 EXPECT_UINT_EQ(xmul(2000, 1), 2000);
2865 1 }
2866
2867 1 static void test_xadd(TestContext *ctx)
2868 {
2869 1 const size_t nearmax = SIZE_MAX - 1;
2870 1 EXPECT_UINT_EQ(xadd(nearmax, 1), nearmax + 1);
2871 1 EXPECT_UINT_EQ(xadd(8, 8), 16);
2872 1 EXPECT_UINT_EQ(xadd(0, 0), 0);
2873 1 }
2874
2875 1 static void test_size_ssub(TestContext *ctx)
2876 {
2877 1 EXPECT_UINT_EQ(size_ssub(0, 1), 0);
2878 1 EXPECT_UINT_EQ(size_ssub(1, 1), 0);
2879 1 EXPECT_UINT_EQ(size_ssub(2, 1), 1);
2880 1 EXPECT_UINT_EQ(size_ssub(191, 170), 21);
2881
2882 1 const size_t m = SIZE_MAX;
2883 1 EXPECT_UINT_EQ(size_ssub(m - 1, m - 2), 1);
2884 1 EXPECT_UINT_EQ(size_ssub(m - 1, m), 0);
2885 1 EXPECT_UINT_EQ(size_ssub(m, m), 0);
2886 1 EXPECT_UINT_EQ(size_ssub(0, m), 0);
2887 1 EXPECT_UINT_EQ(size_ssub(1, m), 0);
2888 1 EXPECT_UINT_EQ(size_ssub(m, 1), m - 1);
2889 1 }
2890
2891 1 static void test_mem_intern(TestContext *ctx)
2892 {
2893 1 const char *ptrs[256];
2894 1 char str[8];
2895
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 1 times.
257 for (unsigned int i = 0; i < ARRAYLEN(ptrs); i++) {
2896 256 size_t len = buf_uint_to_str(i, str);
2897 256 ptrs[i] = mem_intern(str, len);
2898 }
2899
2900 1 EXPECT_STREQ(ptrs[0], "0");
2901 1 EXPECT_STREQ(ptrs[1], "1");
2902 1 EXPECT_STREQ(ptrs[101], "101");
2903 1 EXPECT_STREQ(ptrs[255], "255");
2904
2905
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 1 times.
257 for (unsigned int i = 0; i < ARRAYLEN(ptrs); i++) {
2906 256 size_t len = buf_uint_to_str(i, str);
2907 256 const char *ptr = mem_intern(str, len);
2908 256 EXPECT_PTREQ(ptr, ptrs[i]);
2909 }
2910 1 }
2911
2912 1 static void test_read_file(TestContext *ctx)
2913 {
2914 1 char *buf = NULL;
2915 1 ASSERT_EQ(read_file("/dev/null", &buf, 64), 0);
2916 1 ASSERT_NONNULL(buf);
2917 1 EXPECT_UINT_EQ((unsigned char)buf[0], '\0');
2918 1 free(buf);
2919
2920 1 buf = NULL;
2921 1 errno = 0;
2922 1 EXPECT_EQ(read_file("test/data/", &buf, 64), -1);
2923 1 EXPECT_EQ(errno, EISDIR);
2924 1 EXPECT_NULL(buf);
2925 1 free(buf);
2926
2927 1 buf = NULL;
2928 1 errno = 0;
2929 1 EXPECT_EQ(read_file("test/data/3lines.txt", &buf, 1), -1);
2930 1 EXPECT_EQ(errno, EFBIG);
2931 1 EXPECT_NULL(buf);
2932 1 free(buf);
2933
2934 1 ssize_t size = read_file("test/data/3lines.txt", &buf, 512);
2935 1 EXPECT_EQ(size, 26);
2936 1 ASSERT_NONNULL(buf);
2937 1 size_t pos = 0;
2938 1 const char *line = buf_next_line(buf, &pos, size);
2939 1 EXPECT_STREQ(line, "line #1");
2940 1 EXPECT_EQ(pos, 8);
2941 1 line = buf_next_line(buf, &pos, size);
2942 1 EXPECT_STREQ(line, " line #2");
2943 1 EXPECT_EQ(pos, 17);
2944 1 line = buf_next_line(buf, &pos, size);
2945 1 EXPECT_STREQ(line, " line #3");
2946 1 EXPECT_EQ(pos, 26);
2947 1 free(buf);
2948 1 }
2949
2950 1 static void test_xfopen(TestContext *ctx)
2951 {
2952 1 static const char modes[][4] = {"a", "a+", "r", "r+", "w", "w+"};
2953
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 FOR_EACH_I(i, modes) {
2954 6 FILE *f = xfopen("/dev/null", modes[i], O_CLOEXEC, 0666);
2955 6 IEXPECT_TRUE(f && fclose(f) == 0);
2956 }
2957 1 }
2958
2959 1 static void test_xstdio(TestContext *ctx)
2960 {
2961 1 FILE *f = xfopen("/dev/null", "r+", O_CLOEXEC, 0666);
2962 1 ASSERT_NONNULL(f);
2963
2964 1 char buf[16];
2965 1 EXPECT_NULL(xfgets(buf, sizeof(buf), f));
2966 1 EXPECT_TRUE(xfputs("str", f) != EOF);
2967 1 EXPECT_EQ(xfputc(' ', f), ' ');
2968 1 EXPECT_EQ(xfprintf(f, "fmt %d", 42), 6);
2969 1 EXPECT_EQ(xfflush(f), 0);
2970 1 EXPECT_EQ(fclose(f), 0);
2971 1 }
2972
2973 1 static void test_fd_set_cloexec(TestContext *ctx)
2974 {
2975 1 int fd = open("/dev/null", O_RDONLY);
2976 1 ASSERT_TRUE(fd >= 0);
2977 1 int flags = fcntl(fd, F_GETFD);
2978 1 EXPECT_TRUE(flags >= 0);
2979 1 EXPECT_EQ(flags & FD_CLOEXEC, 0);
2980
2981 1 EXPECT_TRUE(fd_set_cloexec(fd, true));
2982 1 flags = fcntl(fd, F_GETFD);
2983 1 EXPECT_TRUE(flags > 0);
2984 1 EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
2985
2986 // This set of tests is repeated twice, in order to check the special
2987 // case where the F_SETFD operation can be omitted because FD_CLOEXEC
2988 // was already set as requested
2989
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (size_t i = 0; i < 2; i++) {
2990 2 IEXPECT_TRUE(fd_set_cloexec(fd, false));
2991 2 flags = fcntl(fd, F_GETFD);
2992 2 IEXPECT_TRUE(flags >= 0);
2993 2 IEXPECT_EQ(flags & FD_CLOEXEC, 0);
2994 }
2995
2996 1 close(fd);
2997 1 }
2998
2999 1 static void test_fd_set_nonblock(TestContext *ctx)
3000 {
3001 1 int fd = open("/dev/null", O_RDONLY);
3002 1 ASSERT_TRUE(fd >= 0);
3003 1 int flags = fcntl(fd, F_GETFL);
3004 1 EXPECT_TRUE(flags >= 0);
3005 1 EXPECT_EQ(flags & O_NONBLOCK, 0);
3006
3007 1 EXPECT_TRUE(fd_set_nonblock(fd, true));
3008 1 flags = fcntl(fd, F_GETFL);
3009 1 EXPECT_TRUE(flags > 0);
3010 1 EXPECT_EQ(flags & O_NONBLOCK, O_NONBLOCK);
3011
3012
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (size_t i = 0; i < 2; i++) {
3013 2 IEXPECT_TRUE(fd_set_nonblock(fd, false));
3014 2 flags = fcntl(fd, F_GETFL);
3015 2 IEXPECT_TRUE(flags >= 0);
3016 2 IEXPECT_EQ(flags & O_NONBLOCK, 0);
3017 }
3018
3019 1 close(fd);
3020 1 }
3021
3022 1 static void test_fork_exec(TestContext *ctx)
3023 {
3024 1 int fd[3];
3025 1 fd[0] = open("/dev/null", O_RDWR | O_CLOEXEC);
3026 1 ASSERT_TRUE(fd[0] > 0);
3027 1 fd[1] = fd[0];
3028 1 fd[2] = fd[0];
3029
3030 1 const char *argv[] = {"sh", "-c", "exit 95", NULL};
3031 1 pid_t pid = fork_exec(argv, NULL, fd, true);
3032 1 ASSERT_TRUE(pid != -1);
3033 1 int r = wait_child(pid);
3034 1 EXPECT_EQ(r, 95);
3035
3036 1 argv[0] = "sleep";
3037 1 argv[1] = "5";
3038 1 argv[2] = NULL;
3039 1 pid = fork_exec(argv, NULL, fd, true);
3040 1 ASSERT_TRUE(pid != -1);
3041 1 EXPECT_EQ(kill(pid, SIGINT), 0);
3042 1 r = wait_child(pid);
3043 1 EXPECT_TRUE(r >= 256);
3044 1 EXPECT_EQ(r >> 8, SIGINT);
3045
3046 1 EXPECT_EQ(xclose(fd[0]), 0);
3047 1 }
3048
3049 1 static void test_xmemmem(TestContext *ctx)
3050 {
3051 1 static const char haystack[] = "finding a needle in a haystack";
3052 1 const char *needle = xmemmem(haystack, sizeof(haystack), STRN("needle"));
3053 1 ASSERT_NONNULL(needle);
3054 1 EXPECT_PTREQ(needle, haystack + 10);
3055
3056 1 needle = xmemmem(haystack, sizeof(haystack), "\0", 1);
3057 1 ASSERT_NONNULL(needle);
3058 1 EXPECT_PTREQ(needle, haystack + sizeof(haystack) - 1);
3059
3060 1 needle = xmemmem(haystack, sizeof(haystack) - 1, "\0", 1);
3061 1 EXPECT_NULL(needle);
3062
3063 1 needle = xmemmem(haystack, sizeof(haystack), STRN("in "));
3064 1 ASSERT_NONNULL(needle);
3065 1 EXPECT_PTREQ(needle, haystack + 17);
3066
3067 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystack"));
3068 1 ASSERT_NONNULL(needle);
3069 1 EXPECT_PTREQ(needle, haystack + 22);
3070
3071 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystacks"));
3072 1 EXPECT_NULL(needle);
3073
3074 1 needle = xmemmem(haystack, sizeof(haystack), STRN("haystacks"));
3075 1 EXPECT_NULL(needle);
3076 1 }
3077
3078 1 static void test_xmemrchr(TestContext *ctx)
3079 {
3080 1 static const char str[] = "123456789 abcdefedcba 987654321";
3081 1 EXPECT_PTREQ(xmemrchr(str, '9', sizeof(str) - 1), str + 22);
3082 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 1), str + sizeof(str) - 2);
3083 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 2), str);
3084 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str)), str + sizeof(str) - 1);
3085 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str) - 1), NULL);
3086 1 EXPECT_PTREQ(xmemrchr(str, 'z', sizeof(str) - 1), NULL);
3087 1 }
3088
3089 1 static void test_log_level_from_str(TestContext *ctx)
3090 {
3091 1 EXPECT_EQ(log_level_from_str("none"), LOG_LEVEL_NONE);
3092 1 EXPECT_EQ(log_level_from_str("crit"), LOG_LEVEL_CRITICAL);
3093 1 EXPECT_EQ(log_level_from_str("error"), LOG_LEVEL_ERROR);
3094 1 EXPECT_EQ(log_level_from_str("warning"), LOG_LEVEL_WARNING);
3095 1 EXPECT_EQ(log_level_from_str("notice"), LOG_LEVEL_NOTICE);
3096 1 EXPECT_EQ(log_level_from_str("info"), LOG_LEVEL_INFO);
3097 1 EXPECT_EQ(log_level_from_str("debug"), LOG_LEVEL_DEBUG);
3098 1 EXPECT_EQ(log_level_from_str("trace"), LOG_LEVEL_TRACE);
3099
3100 1 EXPECT_EQ(log_level_from_str("xyz"), LOG_LEVEL_INVALID);
3101 1 EXPECT_EQ(log_level_from_str(" "), LOG_LEVEL_INVALID);
3102 1 EXPECT_EQ(log_level_from_str("warn"), LOG_LEVEL_INVALID);
3103 1 EXPECT_EQ(log_level_from_str("errors"), LOG_LEVEL_INVALID);
3104
3105 1 LogLevel default_level = log_level_default();
3106 1 EXPECT_EQ(log_level_from_str(""), default_level);
3107 1 EXPECT_EQ(log_level_from_str(NULL), default_level);
3108 1 }
3109
3110 1 static void test_log_level_to_str(TestContext *ctx)
3111 {
3112 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NONE), "none");
3113 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_CRITICAL), "crit");
3114 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_ERROR), "error");
3115 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_WARNING), "warning");
3116 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NOTICE), "notice");
3117 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_INFO), "info");
3118 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_DEBUG), "debug");
3119 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_TRACE), "trace");
3120 1 }
3121
3122 1 static void test_timespec_subtract(TestContext *ctx)
3123 {
3124 1 struct timespec a = {.tv_sec = 3, .tv_nsec = 5497};
3125 1 struct timespec b = {.tv_sec = 1, .tv_nsec = NS_PER_SECOND - 1};
3126 1 struct timespec r = timespec_subtract(&a, &b);
3127 1 EXPECT_EQ(r.tv_sec, 1);
3128 1 EXPECT_EQ(r.tv_nsec, 5498);
3129
3130 1 b.tv_nsec = 501;
3131 1 r = timespec_subtract(&a, &b);
3132 1 EXPECT_EQ(r.tv_sec, 2);
3133 1 EXPECT_EQ(r.tv_nsec, 4996);
3134 1 }
3135
3136 1 static void test_timespec_cmp(TestContext *ctx)
3137 {
3138 1 struct timespec a = {.tv_sec = 42, .tv_nsec = 980};
3139 1 struct timespec b = {.tv_sec = 41, .tv_nsec = NS_PER_SECOND - 1};
3140 1 EXPECT_EQ(timespec_cmp(&a, &b), 1);
3141 1 b.tv_nsec = a.tv_nsec - 1;
3142 1 EXPECT_EQ(timespec_cmp(&a, &b), 3);
3143 1 a.tv_sec = 0;
3144 1 EXPECT_EQ(timespec_cmp(&a, &b), -1);
3145 1 a.tv_nsec = 0;
3146 1 EXPECT_EQ(timespec_cmp(&a, &b), -3);
3147 1 a.tv_nsec = b.tv_nsec;
3148 1 EXPECT_EQ(timespec_cmp(&a, &b), -2);
3149 1 a.tv_sec = b.tv_sec + 1;
3150 1 EXPECT_EQ(timespec_cmp(&a, &b), 2);
3151 1 a = b;
3152 1 EXPECT_EQ(timespec_cmp(&a, &b), 0);
3153 1 }
3154
3155 1 static void test_timespec_to_str(TestContext *ctx)
3156 {
3157 1 char buf[TIME_STR_BUFSIZE] = "";
3158 1 size_t size = sizeof(buf) - 1;
3159 1 struct timespec ts = {.tv_sec = 0};
3160 1 EXPECT_TRUE(timespecs_equal(&ts, &ts));
3161
3162 1 errno = 0;
3163 1 ts.tv_nsec = NS_PER_SECOND;
3164 1 EXPECT_NULL(timespec_to_str(&ts, buf, size));
3165 1 EXPECT_EQ(errno, EINVAL);
3166
3167 1 errno = 0;
3168 1 ts.tv_nsec = -1;
3169 1 EXPECT_NULL(timespec_to_str(&ts, buf, size));
3170 1 EXPECT_EQ(errno, EINVAL);
3171
3172 // Note: $TZ is set to "UTC" in test_init()
3173 1 ts.tv_sec = 4321;
3174 1 ts.tv_nsec = 9876;
3175 1 const char *r = timespec_to_str(&ts, buf, size);
3176 1 EXPECT_STREQ(r, "1970-01-01 01:12:01.9876 +0000");
3177 1 EXPECT_PTREQ(r, buf);
3178
3179 1 ts.tv_sec = -1;
3180 1 ts.tv_nsec = NS_PER_SECOND - 1;
3181 1 r = timespec_to_str(&ts, buf, size);
3182 1 EXPECT_STREQ(r, "1969-12-31 23:59:59.999999999 +0000");
3183 1 }
3184
3185 1 static void test_progname(TestContext *ctx)
3186 {
3187 1 const char *const args[] = {"arg0", "", NULL};
3188 1 char **arg0 = (char**)args;
3189 1 char **arg1 = arg0 + 1;
3190 1 char **arg2 = arg0 + 2;
3191 1 EXPECT_STREQ(progname(1, arg0, "1"), "arg0");
3192 1 EXPECT_STREQ(progname(1, NULL, "2"), "2");
3193 1 EXPECT_STREQ(progname(0, arg0, "3"), "3");
3194 1 EXPECT_STREQ(progname(1, arg1, "4"), "4");
3195 1 EXPECT_STREQ(progname(1, arg2, "5"), "5");
3196 1 EXPECT_STREQ(progname(0, NULL, NULL), "_PROG_");
3197 1 }
3198
3199 static const TestEntry tests[] = {
3200 TEST(test_util_macros),
3201 TEST(test_is_power_of_2),
3202 TEST(test_xmalloc),
3203 TEST(test_xstreq),
3204 TEST(test_xstrrchr),
3205 TEST(test_str_has_prefix),
3206 TEST(test_str_has_suffix),
3207 TEST(test_hex_decode),
3208 TEST(test_hex_encode_byte),
3209 TEST(test_ascii),
3210 TEST(test_mem_equal_icase),
3211 TEST(test_base64_decode),
3212 TEST(test_base64_encode_block),
3213 TEST(test_base64_encode_final),
3214 TEST(test_string),
3215 TEST(test_string_view),
3216 TEST(test_strview_has_suffix),
3217 TEST(test_strview_remove_matching),
3218 TEST(test_get_delim),
3219 TEST(test_get_delim_str),
3220 TEST(test_str_replace_byte),
3221 TEST(test_strn_replace_byte),
3222 TEST(test_size_str_width),
3223 TEST(test_buf_parse_uintmax),
3224 TEST(test_buf_parse_ulong),
3225 TEST(test_buf_parse_size),
3226 TEST(test_buf_parse_hex_uint),
3227 TEST(test_str_to_int),
3228 TEST(test_str_to_size),
3229 TEST(test_str_to_filepos),
3230 TEST(test_buf_umax_to_hex_str),
3231 TEST(test_parse_filesize),
3232 TEST(test_umax_to_str),
3233 TEST(test_uint_to_str),
3234 TEST(test_ulong_to_str),
3235 TEST(test_buf_umax_to_str),
3236 TEST(test_buf_uint_to_str),
3237 TEST(test_buf_u8_to_str),
3238 TEST(test_file_permissions_to_str),
3239 TEST(test_human_readable_size),
3240 TEST(test_filesize_to_str),
3241 TEST(test_u_char_size),
3242 TEST(test_u_char_width),
3243 TEST(test_u_to_lower),
3244 TEST(test_u_to_upper),
3245 TEST(test_u_is_lower),
3246 TEST(test_u_is_upper),
3247 TEST(test_u_is_ascii_upper),
3248 TEST(test_u_is_cntrl),
3249 TEST(test_u_is_zero_width),
3250 TEST(test_u_is_special_whitespace),
3251 TEST(test_u_is_unprintable),
3252 TEST(test_u_str_width),
3253 TEST(test_u_set_char_raw),
3254 TEST(test_u_set_char),
3255 TEST(test_u_make_printable),
3256 TEST(test_u_get_char),
3257 TEST(test_u_prev_char),
3258 TEST(test_ptr_array),
3259 TEST(test_ptr_array_move),
3260 TEST(test_list),
3261 TEST(test_hashmap),
3262 TEST(test_hashset),
3263 TEST(test_intmap),
3264 TEST(test_round_size_to_next_multiple),
3265 TEST(test_round_size_to_next_power_of_2),
3266 TEST(test_popcount),
3267 TEST(test_ctz),
3268 TEST(test_ffs),
3269 TEST(test_lsbit),
3270 TEST(test_path_dirname_and_path_basename),
3271 TEST(test_path_relative),
3272 TEST(test_path_slice_relative),
3273 TEST(test_short_filename_cwd),
3274 TEST(test_short_filename),
3275 TEST(test_path_absolute),
3276 TEST(test_path_join),
3277 TEST(test_path_parent),
3278 TEST(test_size_increment_wrapped),
3279 TEST(test_size_decrement_wrapped),
3280 TEST(test_size_multiply_overflows),
3281 TEST(test_size_add_overflows),
3282 TEST(test_xmul),
3283 TEST(test_xadd),
3284 TEST(test_size_ssub),
3285 TEST(test_mem_intern),
3286 TEST(test_read_file),
3287 TEST(test_xfopen),
3288 TEST(test_xstdio),
3289 TEST(test_fd_set_cloexec),
3290 TEST(test_fd_set_nonblock),
3291 TEST(test_fork_exec),
3292 TEST(test_xmemmem),
3293 TEST(test_xmemrchr),
3294 TEST(test_log_level_from_str),
3295 TEST(test_log_level_to_str),
3296 TEST(test_timespec_subtract),
3297 TEST(test_timespec_cmp),
3298 TEST(test_timespec_to_str),
3299 TEST(test_progname),
3300 };
3301
3302 const TestGroup util_tests = TEST_GROUP(tests);
3303