dte test coverage


Directory: ./
File: test/util.c
Date: 2025-06-04 06:50:24
Exec Total Coverage
Lines: 2915 2916 99.9%
Functions: 112 112 100.0%
Branches: 97 98 99.0%

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